2014-03-04 78 views
1
SELECT DISTINCT 
viewA.TRID, 
viewA.hits, 
viewA.department, 
viewA.admin, 
viewA.publisher, 
viewA.employee, 
viewA.logincount, 
viewA.registrationdate, 
viewA.firstlogin, 
viewA.lastlogin, 
viewA.`month`, 
viewA.`year`, 
viewA.businesscategory, 
viewA.mail, 
viewA.givenname, 
viewA.sn, 
viewA.departmentnumber, 
viewA.sa_title, 
viewA.title, 
viewA.supemail, 
viewA.regionname 
FROM 
viewA 
LEFT JOIN viewB ON viewA.TRID = viewB.TRID 
WHERE viewB.TRID IS NULL 

我有兩個視圖,其中有大約10K和5K的記錄。他們每個人都很快進入 - 幾分之一秒。當我嘗試從ViewA中獲取所有不在ViewB中的記錄時,它可以工作,但速度很慢。所有底層的TRID字段都是相同的字符集,並且都設置爲varchar(10),索引和表都是Innodb。現在查詢需要16秒。我能做什麼?左側加入兩個視圖很慢?

+0

您是否嘗試刪除左連接並僅使用連接? – DevelopmentIsMyPassion

+0

@AshReva - 這是非常快,但它什麼都沒有返回。 – blankip

+0

這個回報平均有多少條記錄?第二個視圖背後的查詢是什麼樣的? –

回答

4

通常,對於JOIN,MySQL必須爲每個連接記錄進行查找。使用鍵時查找速度很快,但在您的情況下,由於連接的表是視圖,因此沒有任何鍵。

爲了讓MySQL在第一個視圖的每條記錄中運行第二個視圖後面的查詢,我們可以使用子查詢。

SELECT * 
FROM viewA 
WHERE TRID NOT IN (SELECT TRID FROM viewB); 

這應該允許MySQL來獲取所有viewB的TRID值的子查詢(在臨時表),然後做在viewA每個記錄在他們的搜索。

MySQL docs

MySQL只執行一次無關聯子查詢。使用EXPLAIN使 確定給定子查詢確實是不相關的。

+0

當然你不想要'NOT'關鍵字? OP過濾得到'TRID IS NULL'的記錄,所以你可以用'TRID IS NULL'(Robert的答案)替換TRID NOT IN(選擇TRID FROM viewB)。 –

+2

@DavidKnipe,我重新讀了原來的查詢,並且我仍然認爲'NOT IN'是正確的。 –

+0

我沒有看到它自己...除非它是'NULL IN(...)'計算爲false因爲它是'NULL'(我似乎在SQL中回憶'NULL!= NULL')時出現了一些SQL古怪。無論如何,如果羅伯特的解決方案更好,那麼這是一個有爭議的問題,因爲我相信它是。 –

0

很難在MySQL中用視圖優化查詢。我的第一個建議是擺脫distinct,除非你絕對知道它是需要的。

這時,你可能與此查詢比較性能:

select viewA.* 
from viewA 
where not exists (select 1 from viewB where viewB.TRID = viewA.TRID); 

這是很難說的是否會比其他的更好,但它是值得一試,看看這是更好的。

+0

耗時約半秒。我是否設置了我的數據庫錯誤。這些子集非常非正式(沒有表示它們的字段,但是它們是使用一系列規則和案例創建的),主要用於報告。 – blankip

+0

@blankip。 。 。索引可能有幫助。但是,發生的事情是'viewB'運行得很快。然後它必須做一個緩慢的連接與'viewA'結合。您可能會問另一個問題,其中包括視圖的內容以及這兩個SQL語句以及表中的任何索引。然後詢問如何優化。我認爲重寫這個問題是不公平的,因爲它已經有了多個答案。 –