我在MySQL(5.5.31)中有一個約有20M行的表。下面的查詢:DISTINCT導致全表掃描
SELECT DISTINCT mytable.name name FROM mytable
LEFT JOIN mytable_c ON mytable_c.id_c = mytable.id
WHERE mytable.deleted = 0 ORDER BY mytable.date_modified DESC LIMIT 0,21
引起全表掃描,以講解說type
是ALL
和額外的信息是Using where; Using temporary; Using filesort
。解釋的結果:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE mytable ALL NULL NULL NULL NULL 19001156 Using where; Using temporary; Using filesort
1 SIMPLE mytable_c eq_ref PRIMARY PRIMARY 108 mytable.id 1 Using index
沒有加入解釋的樣子:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE mytable index NULL mytablemod 9 NULL 21 Using where; Using temporary
id_c
是mytable_c
和mytable_c
主鍵不具備的每一行不止一行在mytable
。 date_modified
已編入索引。但看起來像MySQL不明白這一點。如果我刪除了DISTINCT子句,那麼explain
使用索引,並且只觸及21行就像預期的那樣。如果我刪除連接它也這樣做。如果沒有連接的全表掃描,有沒有辦法讓它工作? explain
顯示mysql知道它只需要mytable_c
中的一行,它正在使用主鍵,但仍在mytable
上進行全面掃描。
DISTINCT是由於ORM系統生成查詢的原因,在ORM系統中可能會有多行可能由JOIN生成的情況,但SELECT字段的值將始終是唯一的(即,如果JOIN是針對多個 - 值鏈接只有在每個連接行中相同的字段將在SELECT中)。
對於沒有列選擇的表,您有一個外連接。我不明白。 – Strawberry
@Strawberry這個查詢有點簡單,但它*仍*導致全表掃描。這是奇怪的部分 - 無論我是否包含其他表的字段,都會發生全表掃描。 – StasM
試圖回答這種問題而沒有看到a)解釋和b)正確的DDLs是愚蠢的。 (並不是說即使有這些信息我也能做得更好!) – Strawberry