MySQL 索引選擇原則分析(示例庫)

目的sql

數據庫中很重要的設計一部分,莫過於索引了。B+樹索引是MySQL中設計的索引。B+樹索引是基於B+樹基礎發展而來的。數據庫

前面文章MySQL 索引選擇原則分析(一)已經對索引作進一步分析。可是實踐比較少,只是根據理論作了部分分析,下面對MySQL本身推出的測試數據庫及數據作一些SQL的分析。函數

MySQL示例庫下載:測試

http://pan.baidu.com/s/1ntxmgXV優化

一:全列匹配
spa

SELECT * FROM titles WHERE emp_no='10001' AND title='Senior Engineer' AND from_date='1986-06-26';
SELECT * FROM titles WHERE from_date='1986-06-26' AND emp_no='10001' AND title='Senior Engineer';

當按照索引中全部列進行精確匹配("="或"IN")時,索引能夠被用到。注:理論上索引對順序是敏感的,可是因爲MySQL的查詢優化器會自動調整where語句的條件順序以使用適合的索引,所以前面2條SQL的查詢計劃是同樣的。
.net

二:最左前綴匹配
設計

SELECT * FROM titles WHERE emp_no='10001';

SQL查詢計劃能夠看出,key用的是PRIMARY索引,可是key_len爲4,說明只用了索引第一列。當查詢條件精確匹配索引的左邊連續一個或幾個列時,如<emp_no>或<emp_no,title,from_date>,因此能夠被用到,可是隻能用到一部分,即where條件所組成的最左前綴。
code

三:查詢條件用到了索引中列的精確匹配,可是中間某個條件未提供
orm

SELECT * FROM titles WHERE emp_no='10001' AND from_date='1986-06-26';

此時查詢計劃與(二)相同,由於title未提供,因此查詢只用到了索引的第一列,而from_date雖然也在索引中,可是因爲title不存在而沒法和左前綴鏈接,所以須要對結果進行掃描過濾from_date。

四:查詢條件沒有指定索引第一列

SELECT * FROM titles WHERE title='Senior Engineer';
SELECT * FROM titles WHERE from_date='1986-06-26';

因爲不是最左前綴,因此查詢計劃使用的是全表掃描。

五:匹配某列的前綴字符串

SELECT * FROM titles WHERE emp_no='10001' AND title LIKE 'Senior%';
SELECT * FROM titles WHERE emp_no='10001' AND title LIKE '%Senior%';

根據查詢計劃第一句SQL,type是range,key_len爲156,使用了索引的第一列及第二列。

第二劇SQL,查詢計劃與(二)相同,也就使用了索引的第一列。因此LIKE時候也能夠根據具體狀況來進行優化的。

六:範圍查詢

SELECT * FROM titles WHERE emp_no < '10010' AND title='Senior Engineer';
SELECT * FROM titles WHERE emp_no < '10010' AND title='Senior Engineer'
AND from_date BETWEEN '1986-01-01' AND '1986-12-31';
SELECT * FROM titles WHERE emp_no IN ('10001','10002','10003','10004','10005','10006','10007','10008', '10009') AND title='Senior Engineer' AND from_date BETWEEN '1986-01-01' AND '1986-12-31';
SELECT * FROM titles WHERE emp_no BETWEEN '10000' AND '10009' AND title='Senior Engineer'
AND from_date BETWEEN '1986-01-01' AND '1986-12-31';

第一句SQL查詢計劃,type爲range,key_len爲4,使用了索引的第一列。第二句SQL查詢計劃,能夠看出與第一句是同樣的。所以能夠看出,範圍列能夠用到索引,可是範圍列後面的列沒法用到索引。

第三句SQL查詢計劃,type爲range,key_len爲159,也就是使用了索引的全部列。IN使用的是值匹配。

第四句SQL查詢計劃,type爲range,key_len爲159,也就是使用了索引的全部列。因此做用於emp_no上的"BETWEEN"實際上至關於"IN",也就是值匹配。

MySQL的查詢計劃根據type能夠沒法區分範圍索引和多值匹配,由於都是range。所以三、4句SQL纔會都用到索引的全部列。

七:查詢條件中含有函數或表達式

SELECT * FROM titles WHERE emp_no='10001' AND LEFT(title, 6)='Senior';
SELECT * FROM titles WHERE emp_no - 1='10000';
SELECT * FROM titles WHERE emp_no=10000 + 1;

第一句SQL查看查詢計劃,發現key_len爲4,也就是使用了索引中的第一列。所以查詢條件中包含函數或表達式,則MySQL不會爲這列使用索引。

第二句SQL查看查詢計劃,type爲ALL,也就是全表掃描,MySQL沒有使用索引,MySQL的優化器沒有自動的優化常量表達式。

第三句SQL查看查詢計劃,明顯使用了索引的第一列,所以編寫SQL時,常量計算儘可能放到右邊,左邊儘可能少用表達式。

相關文章
相關標籤/搜索