2013-07-23 90 views
0

我有這樣的SQL:如何優化這個SQL在MySQL

select t1.id,t1.type from collect t1 
where t1.type='1' and t1.status='1' 
    and t1.total>(t1.totalComplate+t1.totalIng) 
    and id not in(
      select tid from collect_log t2 
       where t2.tid=t1.id and t2.bid='1146') 
limit 1; 

是是好的,但如果我用一個指示命令其表現似乎不太好和:

select t1.id,t1.type from collect t1 
where t1.type='1' and t1.status='1' 
    and t1.total>(t1.totalComplate+t1.totalIng) 
    and id not in(
      select tid from collect_log t2 
       where t2.tid=t1.id and t2.bid='1146') 
order by t1.id asc 
limit 1; 

它變得更糟。 我如何優化這個?

這裏解釋一下:

id | select_type  | table | type | possible_keys | key | key_len | ref    | rows | Extra      | 
+----+--------------------+-------+------+---------------+-----+---------+-----------------+------+-----------------------------+ 
| 1 | PRIMARY   | t1 | ref | i2,i1,i3  | i1 | 4  | const,const  | 99 | Using where; Using filesort | 
| 2 | DEPENDENT SUBQUERY | t2 | ref | i5   | i5 | 65  | img.t1.id,const | 2 | Using where; Using index 
+0

這是因爲數學正在做的很慢。你有沒有試過把'和t1.total>(t1.totalComplate + t1.totalIng)'放在'limit'的最前面,以減小操作執行結果集的大小? – AgmLauncher

+0

你定義了哪些索引? – eggyal

+0

沒有Agmlauncher,我沒有試過,怎麼樣? –

回答

1

1)如果它沒有這樣做,在collect.id列定義索引可以(如果id對於任何兩條線都不相同):

CREATE UNIQUE INDEX idx_collect_id ON collect (id); 

也許你需要一個collect_log.tidcollect_log.bid的索引。甚至在兩列,就像這樣:

CREATE INDEX idx_collect_log_tidbid ON collect (tid, bid); 

讓它UNIQUE是否有意義,那就是,如果沒有兩行的值相同的(TID,BID)夫婦在表中。例如,如果這些疑問給出相同的結果,它可能可能:

SELECT count(*) FROM collect_log; 

SELECT count(DISTINCT tid, bid) FROM collect_log; 

但是不要讓它UNIQUE如果您不確定這是什麼意思。

2)驗證列的類型collect.typecollect.statuscollect_log.bid。在您的查詢中,您將它們與字符串進行比較,但也許它們被定義爲INT(或SMALLINTTINYINT ...)?在這種情況下,我建議你放棄數字周圍的引號,因爲與整數比較相比,字符串比較非常緩慢。

select t1.id,t1.type from collect t1 
where t1.type=1 and t1.status=1 
    and t1.total>(t1.totalComplate+t1.totalIng) 
    and id not in(
      select tid from collect_log t2 
       where t2.tid=t1.id and t2.bid=1146) 
order by t1.id asc 
limit 1; 

3)如果仍然沒有幫助,只是增加EXPLAIN在您的查詢的面前,你會得到執行計劃。將結果粘貼到此處,我們可以幫助您理解它。其實,我建議你在之前做這個步驟創建任何新的索引。

+0

非常感謝你,我添加了log.tid,bid的索引,但它是Normal類型。好吧,它工作正常,性能變好。我應該把它改爲獨特嗎?和UNIQUE或NORMAL短缺? –

+0

我已經粘貼在這個頁面上的解釋。 –

+0

我更新了我的答案,以解決有關UNIQUE的問題。 –

-1

我會嘗試使用 INNERLEFT JOIN首先擺脫IN聲明。

像這樣(未經):

CREATE INDEX idx_collect_id ON collect (id); 

也可能是唯一索引,如果您:

select t1.id,t1.type 
from collect t1 
    LEFT JOIN collect_log t2 ON t1.id = t2.tid 
where t1.type='1' 
    and t1.status='1' 
    and t1.total>(t1.totalComplate+t1.totalIng) 
    and NOT t2.bid = '1146' 
order by t1.id asc 
limit 1; 
+0

此查詢不會給出相同的結果,它在語義上不等於原始查詢。在collect_log表中沒有id = X的行的情況下,您的查詢不會從collect表中返回行id = X。原始查詢返回該行。在這種情況下,依賴子查詢可以代替IN(...),例如:... AND NOT EXISTS(從collect_log t2中選擇1,其中t2.tid = t1.id和t2.bid = 1146) – krokodilko

+0

對。但是,LEFT JOIN而不是INNER JOIN將返回該行。 – Deruijter