索引可以提高查詢的速度,但並不是使用帶有索引的欄位查詢時,索引都會起作用。使用索引有幾種特殊情況,在這些情況下,有可能使用帶有索引的欄位查詢時,索引並沒有起作用,下面重點介紹這幾種特殊情況。
1. 查詢語句中使用LIKE關鍵字
在查詢語句中
使用 LIKE 關鍵字進行查詢時,如果匹配字串的第一個字元為“%”,索引不會被使用。如果“%”不是在第一個位置,索引就會被使用。
例 1
為了便於理解,我們先查詢 tb_student 表中的資料,SQL 語句和執行結果如下:
mysql> SELECT * FROM tb_student;
+----+------+------+------+
| id | name | age | sex |
+----+------+------+------+
| 1 | 張三 | 12 | 男 |
| 2 | 李四 | 12 | 男 |
| 3 | 王五 | 13 | 女 |
| 4 | 張四 | 13 | 女 |
| 5 | 王四 | 15 | 男 |
| 6 | 趙六 | 12 | 女 |
+----+------+------+------+
6 rows in set (0.03 sec)
下面在查詢語句中使用 LIKE 關鍵字,且匹配的字串中含有“%”符號,使用 EXPLAIN 分析查詢情況,SQL 語句和執行結果如下:
mysql> EXPLAIN SELECT * FROM tb_student WHERE name LIKE '%四'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tb_student
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 6
filtered: 16.67
Extra: Using where
1 row in set, 1 warning (0.01 sec)
mysql> CREATE INDEX index_name ON tb_student(name);
Query OK, 6 rows affected (0.13 sec)
mysql> EXPLAIN SELECT * FROM tb_student WHERE name LIKE '李%'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tb_student
partitions: NULL
type: range
possible_keys: index_name
key: index_name
key_len: 77
ref: NULL
rows: 1
filtered: 100.00
Extra: Using index condition
1 row in set, 1 warning (0.00 sec)
第一個查詢語句執行後,rows 引數的值為 6,表示這次查詢過程中查詢了 6 條記錄;第二個查詢語句執行後,rows 引數的值為 1,表示這次查詢過程只查詢 1 條記錄。同樣是使用 name 欄位進行查詢,因為第一個查詢語句的 LIKE 關鍵字後的字串是以“%”開頭的,所以第一個查詢語句沒有使用索引,而第二個查詢語句使用了索引 index_name。
2. 查詢語句中使用多列索引
多列索引是
在表的多個欄位上建立一個索引,只有查詢條件中使用了這些欄位中的第一個欄位,索引才會被使用。
例 2
在 name 和 age 兩個欄位上建立多列索引,並驗證多列索引的使用情況,SQL 語句和執行結果如下:
mysql> CREATE INDEX index_name_age ON tb_student(name,age);
Query OK, 6 rows affected (0.11 sec)
mysql> EXPLAIN SELECT * FROM tb_student WHERE name LIKE '李%'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tb_student
partitions: NULL
type: range
possible_keys: index_name_age
key: index_name_age
key_len: 77
ref: NULL
rows: 1
filtered: 100.00
Extra: Using index condition
1 row in set, 1 warning (0.05 sec)
mysql> EXPLAIN SELECT * FROM tb_student WHERE age LIKE '12'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tb_student
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 6
filtered: 16.67
Extra: Using where
1 row in set, 1 warning (0.00 sec)
第一條查詢語句的查詢條件使用了 name 欄位,分析結果顯示 rows 引數的值為 1,且查詢過程中使用了 index_name_age 索引。第二條查詢語句的查詢條件使用了 age 欄位,結果顯示 rows 引數的值為 6,且 key 引數的值為 NULL,這說明第二個查詢語句沒有使用索引。
因為 name 欄位是多列索引的第一個欄位,所以只有查詢條件中使用了 name 欄位才會使 index_name_age 索引起作用。
3. 查詢語句中使用OR關鍵字
查詢語句只有 OR 關鍵字時,
如果 OR 前後的兩個條件的列都是索引,那麼查詢中將使用索引。如果 OR 前後有一個條件的列不是索引,那麼查詢中將不使用索引。
例 3
下面演示 OR 關鍵字的使用。
mysql> EXPLAIN SELECT * FROM tb_student WHERE name='張三' or sex='男'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tb_student
partitions: NULL
type: ALL
possible_keys: index_name,index_name_age
key: NULL
key_len: NULL
ref: NULL
rows: 6
filtered: 30.56
Extra: Using where
1 row in set, 1 warning (0.06 sec)
mysql> EXPLAIN SELECT * FROM tb_student WHERE name='張三' or id='12'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tb_student
partitions: NULL
type: index_merge
possible_keys: PRIMARY,index_name,index_name_age
key: index_name,PRIMARY
key_len: 77,4
ref: NULL
rows: 2
filtered: 100.00
Extra: Using union(index_name,PRIMARY); Using where
1 row in set, 1 warning (0.01 sec)
由於 sex 欄位沒有索引,所以第一條查詢語句沒有使用索引;name 欄位和 id 欄位都有索引,所以第二條查詢語句使用了 index_name 和 PRIMARY 索引 。
總結
使用索引查詢記錄時,一定要注意索引的使用情況。例如,LIKE 關鍵字設定的字串不能以“%”開頭;使用多列索引時,查詢條件必須要使用這個索引的第一個欄位;使用 OR 關鍵字時,OR 關鍵字連線的所有條件都必須使用索引。