【老葉觀點】除了常見的建議外,還有幾個要點:
7.1、超過20個長度的字符串列,最好創建前綴索引而非整列索引(例如:ALTER TABLE t1 ADD INDEX(user(20))),可以有效提高索引利用率,不過它的缺點是對這個列排序時用不到前綴索引。前綴索引的長度可以基于對該字段的統計得出,一般略大于平均長度一點就可以了。
7.2、定期用 pt-duplicate-key-checker 工具檢查并刪除重復的索引。比如 index idx1(a, b) 索引已經涵蓋了 index idx2(a),就可以刪除 idx2 索引了。
7.3、有多字段聯合索引時,WHERE中過濾條件的字段順序無需和索引一致,但如果有排序、分組則就必須一致了。
比如有聯合索引 idx1(a, b, c),那么下面的SQL都可以完整用到索引:
~~~
SELECT ... WHERE b = ? AND c = ? AND a = ?; ?--注意到,WHERE中字段順序并沒有和索引字段順序一致
SELECT ... WHERE b = ? AND a?= ? AND c?= ?;
SELECT ... WHERE a?= ? AND b IN (?, ?) AND c = ?;
SELECT ... WHERE a?= ? AND b?= ??ORDER BY c;
SELECT ... WHERE a?= ? AND b IN (?, ?) ORDER BY c;
SELECT ... WHERE a?= ? ORDER BY b, c;
SELECT ... ORDER BY a, b, c; ?-- 可利用聯合索引完成排序
~~~
而下面幾個SQL則只能用到部分索引,或者可利用到ICP特性:
~~~
SELECT ... WHERE b = ? AND a = ?; -- 只能用到 (a, b) 部分
SELECT ... WHERE a IN (?, ?) AND b = ?; -- EXPLAIN顯示只用到 (a, b) 部分索引,同時有ICP
SELECT ... WHERE (a BETWEEN ? AND ?) AND b = ?; -- EXPLAIN顯示只用到 (a, b) 部分索引,同時有ICP
SELECT ... WHERE a = ? AND b IN (?, ?); -- EXPLAIN顯示只用到 (a, b) 部分索引,同時有ICP
SELECT ... WHERE a = ? AND (b BETWEEN ? AND ?) AND c = ?; -- EXPLAIN顯示用到 (a, b, c) 整個索引,同時有ICP
SELECT ... WHERE a = ? AND c = ?; -- EXPLAIN顯示只用到 (a) 部分索引,同時有ICP
SELECT ... WHERE a = ? AND c >= ?; -- EXPLAIN顯示只用到 (a) 部分索引,同時有ICP
ICP(index condition pushdown)是MySQL 5.6的新特性,其機制會讓索引的其他部分也參與過濾,減少引擎層和server層之間的數據傳輸和回表請求,通常情況下可大幅提升查詢效率。
~~~
下面的幾個SQL完全用不到該索引:
~~~
SELECT ... WHERE b?= ?;
SELECT ... WHERE b?= ??AND c = ?;
SELECT ... WHERE b?= ??AND c = ?;
SELECT ... ORDER?BY b;
SELECT ... ORDER?BY b, a;
~~~
從上面的幾個例子就能看的出來,以往強調的WHERE條件字段順序要和索引順序一致才能使用索引的 “常識性誤導”?無需嚴格遵守。
此外,有些時候查詢優化器指定的索引或執行計劃可能并不是最優的,可以手工指定最優索引,或者修改session級的?[optimizer_switch](http://dev.mysql.com/doc/refman/5.6/en/switchable-optimizations.html)?選項,關閉某些導致效果反而更差的特性(比如index merge通常是好事,但也遇到過用上index merge后反而更差的,這時候要么強制指定其中一個索引,要么可以臨時關閉 index merge 特性)。