2011-04-05 76 views
1
設定爲加入和索引組

比方說,我們有一個共同的加入類似下面:如何通過查詢

EXPLAIN SELECT * 
FROM visited_links vl 
JOIN device_tracker dt ON (dt.Client_id = vl.Client_id 
AND dt.Device_id = vl.Device_id) 
GROUP BY dt.id 

如果我們執行一個解釋,它說:

id select_type table type possible_keys   key  key_len ref       rows Extra 
1 SIMPLE  vl  index NULL     vl_id  273  NULL      1977 Using index; Using temporary; Using filesort 
1 SIMPLE  dt  ref  Device_id,Device_id_2 Device_id 257  datumprotect.vl.device_id 4  Using where 

我知道有時在使用group by時有時很難選擇正確的索引,但是,我可以設置哪些索引以避免在此查詢中使用「temporary,using filesort」?爲什麼發生這種情況?特別是爲什麼在使用索引後會發生這種情況?

回答

0

你不發表您的指標,但首先,你會希望有一個(client_id, device_id)指數visited_links,並(client_id, device_id, id)device_tracker確保查詢完全索引。

從優秀的第191頁高性能MySQL,第2版。

當MySQL無法使用索引時,它有兩種GROUP BY策略:它可以使用臨時表或文件夾來執行分組。根據查詢,任何一個都可以更高效。您可以強制優化器使用SQL_BIG_RESULT和SQL_SMALL_RESULT優化器提示選擇一種方法或另一種方法。

在你的情況,我認爲這個問題源於加入多個列並使用GROUP BY在一起,甚至在建議的索引已經到位之後。如果刪除(a)加入條件之一或(b)GROUP BY,則不需要文件夾。

但是,請記住,文件夾並不總是使用實際文件,如果結果集足夠小,它也可以完全在內存緩衝區中執行,因此性能損失可能會很小。也考慮查詢的掛鐘時間。

HTH!

1

需要指出的一點是,select(*在本例中)返回的字段應該在GROUP BY子句中,或者使用諸如SUM()或MAX()之類的聚合函數。否則會發生意外結果。這是因爲如果沒有告知數據庫如何選擇不在group by子句中的字段,則可能會隨機獲得該組的任何成員。


我看待它的方式是將查詢分解爲位。

  1. 你有一個連接上(dt.Client_id = vl.Client_id和dt.Device_id = vl.Device_id),因此所有這些領域都應該各自表中的索引。

  2. 您正在使用GROUP BY dt.id所以你需要包括dt.id

的索引,但...

上(dt.client_id,dt.device_id指數, DT。ID)將不會被

的指數爲小組作業上(dt.id,dt.client_id,dt.device_id)將不會爲參加工作。

有時你最終會遇到一個不能使用索引的查詢。

另請參閱: http://ntsrikanth.blogspot.com/2007/11/sql-query-order-of-execution.html