1. 程式人生 > 實用技巧 >mysql中走與不走索引的情況彙集(待全量實驗)

mysql中走與不走索引的情況彙集(待全量實驗)

說明

在MySQL中,並不是你建立了索引,並且你在SQL中使用到了該列,MySQL就肯定會使用到那些索引的,有一些情況很可能在你不知不覺中,你就“成功的避開了”MySQL的所有索引。

索引列參與計算

如果where條件中age列中使用了計算,則不會使用該索引。如果需要計算,千萬不要計算到索引列,想方設法讓其計算到表示式的另一邊去。

    SELECT `sname` FROM `t_stu` WHERE `age`=20;       -- 會使用索引
    SELECT `sname` FROM `t_stu` WHERE `age`+10=30;    -- 不會使用索引!!因為所有索引列參與了計算
SELECT `sname` FROM `t_stu` WHERE `age`=30-10; -- 會使用索引

索引列使用了函式

同樣的道理,索引列使用了函式,一樣會導致相同的後果

SELECT `sname` FROM `stu` WHERE concat(`sname`,'abc') ='Jaskeyabc';   -- 不會使用索引,因為使用了函式運算,原理與上面相同
SELECT `sname` FROM `stu` WHERE `sname`=concat('Jaskey','abc');      -- 會使用索引

索引列使用了Like %XXX

SELECT * FROM `houdunwang` WHERE `uname` LIKE '字首%' -- 走索引
SELECT * FROM `houdunwang` WHERE `uname` LIKE '%字尾' -- 掃描全表,不走索引

所以當需要搜尋email列中.com結尾的字串而email上希望走索引時候,可以考慮資料庫儲存一個反向的內容reverse_email

SELECT * FROM `table` WHERE `reverse_email` LIKE REVERSE('%.com'); -- 走索引

  注:以上如果你使用REVERSE(email) = REVERSE(’%.com’),一樣得不到你想要的結果,因為你在索引列email列上使用了函式,MySQL不會使用該列索引
同樣的,索引列上使用正則表示式也不會走索引。

字串列與數字直接比較

這是一個坑,假設有一張表,裡面的a列是一個字元char型別,且a上建立了索引,你用它與數字型別做比較判斷的話:

CREATE TABLE `t1` (`a` char(10));
SELECT * FROM `t1` WHERE `a`='1' -- 走索引
SELECT * FROM `t2` WHERE `a`=1 -- 字串和數字比較,不走索引!

但是如果那個表那個列是一個數字型別,拿來和字元型別的做比較,則不會影響到使用索引

CREATE TABLE `t2` (`b` int);
SELECT * FROM `t2` WHERE `b`='1' -- 雖然b是數字型別,和'1'比較依然走索引

但是,無論如何,這種額外的隱式型別轉換都是開銷,而且由於有字元和數字比就不走索引的情況,故建議避免一切隱式型別轉換

儘量避免 OR 操作

select * from dept where dname='jaskey' or loc='bj' or deptno=45 
--如果條件中有or,即使其中有條件帶索引也不會使用。換言之,就是要求使用的所有欄位,都必須建立索引

所以除非每個列都建立了索引,否則不建議使用OR,在多列OR中,可以考慮用UNION 替換

select * from dept where dname='jaskey' union
select * from dept where loc='bj' union
select * from dept where deptno=45

ORDER BY操作

在ORDER BY操作中,排序的列同時也在WHERE中時,MYSQL將無法使用索引;

MySQL索引通常是被用於提高WHERE條件的資料行匹配或者執行聯結操作時匹配其它表的資料行的搜尋速度。

MySQL也能利用索引來快速地執行ORDER BY和GROUP BY語句的排序和分組操作。

通過索引優化來實現MySQL的ORDER BY語句優化:

1、ORDER BY的索引優化。如果一個SQL語句形如:

SELECT [column1],[column2],…. FROM [TABLE] ORDER BY [sort];
在[sort]這個欄位上建立索引就可以實現利用索引進行order by 優化。

2、WHERE + ORDER BY的索引優化,形如:

SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] = [value] ORDER BY [sort];
建立一個聯合索引(columnX,sort)來實現order by 優化。
注意:如果columnX對應多個值,如下面語句就無法利用索引來實現order by的優化
SELECT [column1],[column2],…. FROM [TABLE] WHERE [columnX] IN ([value1],[value2],…) ORDER BY[sort];

3、WHERE+ 多個欄位ORDER BY

SELECT * FROM [table] WHERE uid=1 ORDER x,y LIMIT 0,10;
建立索引(uid,x,y)實現order by的優化,比建立(x,y,uid)索引效果要好得多。
MySQL Order By不能使用索引來優化排序的情況
* 對不同的索引鍵做 ORDER BY :(key1,key2分別建立索引)
SELECT * FROM t1 ORDER BY key1, key2;
* 在非連續的索引鍵部分上做 ORDER BY:(key_part1,key_part2建立聯合索引;key2建立索引)
SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2;
* 同時使用了 ASC 和 DESC:(key_part1,key_part2建立聯合索引)
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
* 用於搜尋記錄的索引鍵和做 ORDER BY 的不是同一個:(key1,key2分別建立索引)
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
* 如果在WHERE和ORDER BY的欄位上應用表示式(函式)時,則無法利用索引來實現order by的優化
SELECT * FROM t1 ORDER BY YEAR(logindate) LIMIT 0,10;

特別提示:

1>mysql一次查詢只能使用一個索引。如果要對多個欄位使用索引,建立複合索引。
2>在ORDER BY操作中,MySQL只有在排序條件不是一個查詢條件表示式的情況下才使用索引。