MySQL|索引應用

能夠先看下這篇理論介紹: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


以上,索引的應用實例,若是有疏漏,請指導!


算法channel會有系統地,認真地推送:基礎算法/機器學習/深度學習/spark/tensorflow等全棧內容。期待您的參與!QQ交流羣: 646901659 或進入公衆號界面->導讀系列下,進入微信討論羣。

本文分享自微信公衆號 - Python與算法社區(alg-channel)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索