假设我们有一个如下所示的通用连接:
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 时很难选择正确的索引,但是,我可以设置哪些索引来避免在此查询中“使用临时文件,使用文件排序”?为什么会这样?特别是,为什么在使用索引后会发生这种情况?
最佳答案
需要提及的一点是,select(在本例中为 *)返回的字段应该在 GROUP BY 子句中或使用聚合函数,例如 SUM() 或 MAX()。否则可能会出现意想不到的结果。这是因为如果数据库没有被告知如何选择不在 group by 子句中的字段,您可能会随机获得该组的任何成员。
我看待它的方式是将查询分解成位。
您有一个连接(dt.Client_id = vl.Client_id 和 dt.Device_id = vl.Device_id),因此所有这些字段都应该在各自的表中建立索引。
您正在使用 GROUP BY dt.id,因此您需要一个包含 dt.id 的索引
但是...
(dt.client_id,dt.device_id,dt.id) 上的索引不适用于 GROUP BY
和
(dt.id, dt.client_id, dt.device_id) 上的索引不适用于连接。
有时您最终会得到一个无法使用索引的查询。
另见: http://ntsrikanth.blogspot.com/2007/11/sql-query-order-of-execution.html
关于mysql - 如何为查询设置连接和分组索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5552319/