咱们日常所说的索引,若是没有特别指明,都是指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,我认为写得很好 函数