能夠先看下這篇理論介紹:html
MySQL|索引背後
mysql
01
算法
MySQL的幾種KEYsql
PRIMARY KEY 有兩個做用,一是約束做用(constraint),用來規範一個存儲主鍵和惟一性,但同時也在此key上創建了一個主鍵索引;每一個表都應該有一個主鍵,而且每一個表只能有一個主鍵。數據庫
UNIQUE KEY 與 PRIMARY KEY類似,只不過每一個表能夠有多個主鍵。微信
FOREIGN KEY 也是在這個key上創建一個index ,以下所示: FOREIGN KEY(emp_no) REFERENCES employees (emp_no) ON DELETE CASCADE,代表此表的emp_no引用的是employees表的emp_no,同時ON DELETE CASCADE指明一旦刪除employees的某emp_no的記錄,相應也會在這個表中刪除這條記錄。機器學習
02
編輯器
employees示例庫學習
看這個概念前,先介紹一個實例庫。flex
導入MySql的employees庫,下載地址:
https://dev.mysql.com/doc/employee/en/employees-installation.html
解壓縮後,找到 employees.sql,注意最後幾行的source ***.dump,在往數據庫中導入時候,最後指定它的絕對路徑,而後導入。
這個庫包括6張表,關係以下:
03
索引index
看下titles表裏面的索引,
SHOW INDEX FROM employees.titles;
titles表的主索引爲<emp_no, title, from_date>
titles表的行數爲
443307 |
04
全列匹配
查看嚴格按照索引組合的查詢解釋:
EXPLAIN SELECT * FROM employees.titles WHERE emp_no='10002' AND title='Staff' AND from_date='1996-08-03';
很明顯,當按照索引中全部列進行精確匹配(這裏精確匹配指「=」或「IN」匹配)時,索引能夠被用到。
05
最左前綴匹配
EXPLAIN SELECT * FROM employees.titles WHERE emp_no='10002';
條件所組成的最左前綴。上面的查詢從分析結果看用到了PRIMARY索引,可是key_len爲4,說明只用到了索引的第一列前綴。
06
缺失最左前綴匹配
EXPLAIN SELECT * FROM employees.titles WHERE title='Staff' AND from_date='1996-08-03';
因爲不是最左前綴,這樣的查詢顯然用不到索引。
07
範圍查詢
EXPLAIN SELECT * FROM employees.titles WHERE emp_no<'10010'
最左前綴的範圍列能夠用到索引,範圍索引只能有一個。
08
每張表都得建索引?
答案是否認的。由於添加索引須要付出相應的代價,索引文件自己要消耗存儲空間,同時索引會加劇插入、刪除和修改記錄時的負擔。通常兩種狀況下不建議建索引。
第一種狀況是表記錄比較少,例如一兩千條甚至只有幾百條記錄的表,不必建索引,讓查詢作全表掃描就行了。
另外一種索引的選擇性較低時不須要創建索引。所謂索引的選擇性(Selectivity),是指不重複的索引值(也叫基數,Cardinality)與表記錄數(#T)的比值:
Index Selectivity = Cardinality / #T
以下所示爲employees的cardinality:
09
根據選擇性創建索引
SELECT count(DISTINCT(concat(first_name, last_name)))/count(*) AS Selectivity FROM employees.employees;
獲得的選擇值爲:0.9313
可是這樣的索引組合可能致使鍵值過長。
取last_name的前4個字符:
SELECT count(DISTINCT(concat(first_name, left(last_name, 4))))/count(*) AS Selectivity FROM employees.employees;
獲得的選擇值爲:0.900
已經不錯了。
沒有添加組合索引前的查詢:
SELECT * FROM employees.employees WHERE first_name='Eric' AND last_name='Anido'
耗時:0.609s
添加組合索引:
ALTER TABLE employees.employees ADD INDEX `first_name_last_name4` (first_name, last_name(4));
再次查詢,耗時:0.0009s
前綴索引兼顧索引大小和查詢速度,可是其缺點是不能用於ORDER BY和GROUP BY操做,也不能用於Covering index。
參考文章:
http://blog.codinglabs.org/articles/theory-of-mysql-index.html
以上,索引的應用實例,若是有疏漏,請指導!
本文分享自微信公衆號 - Python與算法社區(alg-channel)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。