咱們日常所說的索引,若是沒有特別指明,都是指B+樹結構組織的B-Tree索引。其中彙集索引,次要索引,覆蓋索引,複合索引,前綴索引,惟一索引默認都是使用B+樹索引,統稱索引。固然,除了B+樹這種類型的索引以外,還有哈稀索引(hash index)等。 php
這裏主要討論一下InnoDB B-Tree索引的使用,不提設計,只管使用。B-Tree索引主要做用於WHERE和ORDER BY子句。這裏討論的均在MySQL-Server-5.1.38測試 mysql
CREATE TABLE `friends` ( `ID` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `uid` bigint(20) UNSIGNED NOT NULL DEFAULT '0', `fuid` bigint(20) UNSIGNED NOT NULL DEFAULT '0', `fname` varchar(50) NOT NULL DEFAULT '', `fpicture` varchar(150) NOT NULL DEFAULT '', `fsex` tinyint(1) NOT NULL DEFAULT '0', `status` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; ALTER TABLE `friends` ADD INDEX uid_fuid (uid, fuid);
1.若是索引了多列,要遵照最左前綴法則。所謂最左前列,指的是查詢從索引的最左前列開始,而且不跳過索引中的列。
第2條語句,從索引的第二列開始查找,使用索引失敗,致使MySQL採用ALL訪問策略,即全表查詢.在開發中,應該儘可能避免全表查詢。
2.當MySQL一旦估計檢查的行數可能會」太多」,範圍查找優化將不會被使用。
第2條語句使用了全表查詢,它與第1條語句惟一的區別在於須要檢查的行數遠遠多於第1條語句。在應用中,可能不會碰到這麼大的查詢,可是應該避免這樣的查詢出現: select uid from users where registered < 1295001384
3.索引列不該該做爲表達式的一部分,即也不能在索引列上使用函數
第2和3條語句都有使用表達式,索引派不上用場。
4.儘可能借用覆蓋索引,減小select * from …語句使用
第1句Extra中使用了Using index表示使用了覆蓋索引。第3句也使用了覆蓋索引,雖然ID不在索引uid_fuid索引列中,可是InnoDB二次索引(second index)葉子頁的值就是PK值,不一樣於MyISAM。Extra部分的Using index表示應用了索引,不要跟type中的index混淆。第2句沒有使用覆蓋索引,由於fsex不在索引中。
5.ORDER BY子句,儘可能使用Index方式排序,避免使用FileSort方式排序
MySQL支持二種方式的排序,FileSort和Index,後者效率高,它指MySQL掃描索引自己完成排序。FileSort方式效率較低。ORDER BY知足如下狀況,會使用Index方式排序:
a)ORDER BY 語句使用索引最左前列。參見第1句
b)使用Where子句與Order BY子句條件列組合知足索引最左前列。參見第2句.
如下狀況,會使用FileSort方式的查詢 sql
6.慎用left join語句,避免建立臨時表 使用left join語句的時候,避免出現建立臨時表。儘可能不要用left join,分而治之。非要使用的時候,要詢問本身是否是真要必需要使用。
7.高選擇性索引列。 儘可能使用高選擇性的過引來過濾數據。高選擇性指Cardinality/#T越接近1,選擇性越高,其中Cardinality指表中索引列不重複值(行)的總數。PK和惟一索引,具備最高的選擇性,即1。推薦可選性達到20%以上。
這裏有二個索引可供使用,而MySQL選擇PRIMARY,是由於它具備更高的選擇性。
8.謹防where子句中的OR。where語句使用or,且沒有使用覆蓋索引,會進行全表掃描。應該儘可能避免這樣OR語句。儘可能使用UNION代替OR
第1句雖然使用了索引,可是查行時間依然不能夠恭維,mysql要檢查的行不少,可是返回的行卻不多.Extra中的using where表示須要經過where子句扔棄不須要的數據行。
9.LIMIT與覆蓋索引 limit子句,使用覆蓋索引時比沒有使用覆蓋索引會快不少 app
1. MySQL Explain, 這裏附一份由網友胡中泉分享的Explain的PPT,我認爲寫得很好 函數