Mysql
對兩個索引列使用“OR”不使用索引
在下面的查詢中,
from
和tid
是replies
表的索引。SELECT * FROM `replies` WHERE `from`="<userId>" OR `tid` IN (SELECT `tid` FROM `posts` WHERE `from`="<userId>")
通過使用“OR”,它似乎進行了全表掃描(約 300 萬行)。
EXPLAIN
說可能的密鑰是,from
但它不使用任何密鑰。但是,在下面的查詢中,
frid_lt
並被frid_gt
索引。這兩列在一個複雜的索引中(frid_lt,frid_gt),但frid_gt
也有自己的索引。SELECT `mid` FROM `messages` WHERE `frid_lt`="<userId>" OR `frid_gt`="<userId>"
這個查詢確實使用了兩個索引。上面寫著“
EXPLAIN
index_merge”和“使用 sort_union(frid_lt,frid_gt); 使用 where”。**為什麼第一個查詢不使用索引合併?
我可以做任何改進以使引擎也使用索引合併嗎?**
OR
沒有優化好。一個常見的解決方法是使用UNION
:( SELECT * FROM replies WHERE `from` = "..." ) UNION ALL -- or UNION DISTINCT if you know there are no dups ( SELECT r.* FROM replies AS r JOIN posts AS p ON p.tid = r.tid WHERE p.from = "..." )
請注意,我還避免了通常效率低下的
IN ( SELECT ... )
為了進一步提高性能,請使用以下索引:
replies: INDEX(`from`) posts: INDEX(`from`, tid) -- in this order replies: INDEX(tid)
(請注意,這
PRIMARY KEY
是一個索引,所以不要添加冗餘索引。)在您的第二個範例中,您遇到的“索引合併”可能會也可能不會比
UNION
.哦,這是一個更新
要優化
UPDATE
,請做兩個單獨的UPDATEs
(不UNION
,不OR
)。一本正經地檢查from
。另一個是類似於上面第二個選擇的“多表更新”(參見手冊)。