2013-11-15 116 views
1

我無法弄清楚爲什麼在Query2中的'order by'子句導致它超過一分鐘,而第一個子句立即返回結果。有沒有更好的辦法 '由序' 要做到這一點Mysql Order By By Group By造成查詢速度很慢

快速:

select c.id, max(date(a.sent)) as sent, 
    if(c.id in (select id from bin where (num=1 or num=2)),1,0) as done 
from test c, test2 a 
where c.id=a.id 
group by c.id 
limit 1; 

select c.id, max(date(a.sent)) as sent, 
    if(c.id in (select id from bin where (num=1 or num=2)),1,0) as done 
from test c, test2 a 
where c.id=a.id 
group by c.id 
order by done, sent 
limit 1; 

回答

1

這是因爲在order by子句中的 「列」 並不是真正的列,但用於在查詢中其他地方進行計算的別名。因此,它們沒有編入索引,服務器必須立即訂購它們。使用聯接來計算done,而不是子查詢,可能會加速很多。

+0

對於大多數現代的RDBMS,子查詢並不比聯接更差。對於舊的關係型數據庫來說,這只是真的,他們無法弄清楚兩者是否相同。今天,有時一個子查詢是一個更好的方法去...這一切都取決於。 –

0

如果您要回收所有記錄,排序不應該花費太多時間,即使它們是計算/非索引字段。但是,您正在使用「限制1」。這改變了優化器的方法。

在第一種情況下,您按ID排序。既然你有「限制1」,並且ID可能有一個索引,優化器可以通過ID去ID,當它得到一個匹配WHERE子句的記錄時,它可以返回。

但是,在第二個查詢中,即使您只需要1條記錄,優化程序也不會知道哪個是除非計算整個集合(因爲您沒有「限制1」),然後返回只有第一個。

取下「限制1」並比較兩個查詢。如果差異仍然存在,則可能是另一個問題。

很難說什麼最適合您的卷。試試這個查詢:

select id, max(date(sent)) as sent, 0 As done 
from test2 
where exists (select 1 from bin where bin.id=test2.id and num not in (1,2)) 
group by id 
union all 
select id, max(date(sent)) as sent, 1 As done 
from test2 
where exists (select 1 from bin where bin.id=test2.id and num in (1,2)) 
group by id 
order by done, sent 
limit 1 

SQL Fiddle is here如果你想調整它。

我遺漏了測試表,因爲您沒有取回除了ID之外的任何字段,而ID已經在test2上。如果你需要測試其他領域,你將不得不調整它。

+0

你是對的。我只運行了沒有限制1的兩個查詢,而「快速」版本實際上比「快速」版本跑得慢。很明顯,「限制1」正在產生影響。是的,我真的只想返回一個記錄。有什麼更好的方法來做到這一點? – user2029890

+0

謝謝。絕對更快,但仍然不能快速使用。我確實需要'測試'表中的數據,我只是沒有在示例中包含它。一張桌子有大約30萬條記錄,另一張大約有200萬條記錄。 – user2029890

+0

好的,這三個表中每一個有多少記錄:test,test2,bin? –