让咱们先看看下面的这段MySQL代码:mysql
mysql> SELECT id FROM user WHERE id + 1 = 2;
咱们会发现,在上面这段SQL查询语句中,咱们给的条件是一个有变量的表达式,若是咱们此时的id列上是存在索引的,那上面的语句能不能使用到索引呢?
答案是不能的,由于MySQL没法自动的解析 id + 1 = 2 这个条件语句,尽管咱们能够一眼的看出来此时等价于 id = 1,可是这种作法是没法使用到索引的,所以咱们在查询的时候,应该使得索引列不能是表达式的一部分,也不能是函数的参数。程序员
若是咱们须要在某一列,例如存放url的一列数据上添加索引来加快查询的速度,咱们先看看url数据的特色,长,相似的还有TEXT类型的数据等,这些都是一些很长,占据很大空间的数据,并且会使得对应的索引大且慢。这时候咱们可使用一些优化的索引策略,例如前缀索引。前缀索引与通常的索引不一样,他在查询的时候并不会比对该列数据的全部值,而只是比对它的前面的一部分数据。这样会使得索引变得更加灵活有效率,可是却下降了索引选择性。
什么是索引选择性呢?咱们给定一个公示:
索引选择性 = 不一样的索引值 / 数据表的记录总数
首先思考,为何会有所谓的不一样索引值和相同的索引值?这都要创建在咱们是使用前缀索引这种方式创建索引的基础上。例若有两个数据,“abcalkjsdhgasdfasdf”和“abcalaasdasdqwe”。很显然这两个数据是大相径庭的,可是若是咱们规定前缀索引的长度是数据的前五个字符,那么会发现这两个数据的索引值都是“abcal”,即这两个数据的索引值是同样的。所以也就下降了索引选择性。简单来讲,索引选择性越高,咱们经过索引值能查找到惟一的数据的可能性就越大,索引选择性越低,咱们经过索引值能查找到的惟一的数据的可能性就越小。那么这是否就意味着前缀索引是一个不好的选择呢?并不,由于通常状况下使用恰当的前缀索引,也是能够准确的进行数据的查询,而且可以节省空间的,并且对于BLOB,TEXT或者很长的VARCHAR类型的列,必须使用前缀索引,由于MySQL不容许索引这些列的完整长度。sql
首先,若是一个数据表有3个列,那么咱们为每个列都单独的建立一个索引,是否是就可以使得在查询的时候,不管进行怎样的查找,咱们都能得到最快的效率呢?进行下面的表格创建语句:函数
mysql> CREATE TABLE temp (c1 INTEGER,c2 INTEGER,KEY (c1),KEY (c2));
事实证实,在实际的操做中,这种为每个列都创建一个索引的“单纯”的想法,对查找的效率提高很是的有限,与最佳的索引方案每每效率差距了几个量级。
在MySQL5.0以后的版本多出了“索引合并”的策略,必定程度上是帮程序员优化了这种在一个数据表上建立许多单列索引的操做,可是仍是不建议使用这种索引策略。在MySQL5.0以前的版本,若是咱们为表film_actor的字段film_id和actor_id分别建立一个单列索引,而后执行如下的查询操做:性能
mysql> SELECT film_id, actor_id FROM film_actor WHERE film_id = 1 OR actor_id = 1;
事实上,在这个查询语句中,咱们所定义的两个单列索引都没法帮忙提升效率,甚至于在老版本的MySQL中,将会使用全表扫描来完成这个查询,这就使得这个索引策略变得彻底没有意义。
除非将上面的语句改写成如下的形式:优化
mysql> SELECT actor_id, film_id FROM film_actor WHERE actor_id = 1 UNION ALL SELECT actor_id, film_id FROM film_actor WHERE film_id = 1
即将查询改写成两个查询的交集,即每一个查询都只是用一个列做为判断的条件,拿着整MySQL就会很天然的运用这个列的索引。url
所以咱们仍是建议在须要在多个列上创建索引的时候不要单独的给每一个列创建一个索引,而是选择创建一个多列索引。spa
mysql> CREATE TABLE temp (c1 INTEGER,c2 INTEGER,KEY (c1, c2));
这个时候选择一个合适的索引列顺序就显得很是重要了,由于咱们知道,若是咱们使用默认的B-Tree创建一个多列索引的话,MySQL会按照咱们建立时候指定的顺序创建索引,即先排c1,再在c1排列好的基础上排列c2。
并且查询的时候每次都是从左开始扫描,意味着若是你第一个查询的列并非索引的最左列,那这个索引对于你来讲就形同虚设。
咱们看看以下的一个查询语句:指针
mysql> SELECT * FROM payment WHERE staff_id = 2 AND customer_id = 584;
那咱们是应该创建一个(staff_id, customer_id)的多列索引仍是将他们的顺序颠倒过来呢?咱们能够先看看这两个条件的数据量有多大:code
sum(staff_id = 2) = 7992 sum(customer_id = 584) = 30
根据经验,咱们应该将索引列customer_id 放到前面,由于对应条件值的数据量更小。所以如何选择索引列的顺序仍是应该根据具体的状况来肯定,没有惟一的准则。
聚簇索引其实只是一种特殊的B-Tree索引,他并非一种区别于其余索引的单独的索引形式,而是一种存储方式。
当使用聚簇索引的时候,全部的数据都存储在索引树的叶子节点上。
下图展现了聚簇索引中的记录是如何存放的:
在建立聚簇索引时,InnoDB使用主键做为索引列汇集数据。若是数据表没有定义主键,则会选择一个惟一的非空索引代替,若是没有这样的索引InnoDB则会隐式定义一个主键来做为聚簇索引。
聚簇索引有如下的优势:
同时,聚簇索引也有如下的缺陷:
因为聚簇索引的内容比较多,会专门出一篇来较为深刻的将聚簇索引。