这篇文章中已经说了索引是个什么东西,并且是怎么运作的,但是并不会用啊。
这篇文章就是说说,索引怎么用,为什么那么用。
使用索引有什么代价
1、一个索引其实就是一个B+树,会占地方。如果你有的是地方,那就忽略
2、每次增删改,都不仅仅要维护聚簇索引,还有维护你创建的说有索引,如果你创建了特别多的索引那这里就会变慢了。
不是所有查询都会用上索引
先看一下联合索引问题,面试经常会问联合索引最左原则
等
为什么会存在这样的原则,为什么顺序很重要?
简单为用户表建立name
,phone
,address
联合索引
这个联合索引会在创建一个B+树,这个树的叶子节点上数据只有主键和这三个参数。排序方式为先按照name
生序排列,如果相同的name
,在按照phone
排序。最后按照address
生序排序。
WHERE name = 'yusheng' AND phone = '15123983239' AND address= 上海市长宁区
这个条件是可以使用该联合索引,并且三列都会被使用。
因为叶子节点中的数据排序先按照name
排序的,所以第一次查询只需要在该联合索引的B+树中查询name
的值为yusheng的列即可,之后按在按照叶子节点phone获取,最后address。因为叶子节点的数据是按照这三列排序的,所以很容易查出来。
WHERE phone = '15123983239 AND 'name = 'yusheng' AND address= 上海市长宁区
按照上面的逻辑是不能用的,因为首先用phone去查询的话,毫无顺序。(因为顺序是先按照name排序,所以每个名字下的phone是对的,但是多个名字下的phone就没有顺序了,address也是如此)。但是其实是可以用的,而且和第一个相同。
这是因为mysql在查询之前会对语句进行优化,mysql知道这三个是联合索引,所以在执行查询的时候,会自动调换顺序。
WHERE phone = '15123983239 AND address= 上海市长宁区
这个用不上,因为上一个中就说了,排序是先按照name
排序,虽然每个名字下phone是按照顺序的,但是不同名字下,phone就是无序的,address同理。
WHERE name = 'yusheng' AND address= 上海市长宁区
这个只能用上一半吧,因为name可以使用该联合索引,但是不同phone下面的address是无序的。
WHERE name = 'yu%' AND phone = '15123983239' AND address= 上海市长宁区
这个可以使用,因为差别和第一个只在name上面,因为name是字符串,叶子节点是按照字符串升序排列的,字符串比较会先比较第一个字符,之后在比较第二个字符。所以按照开头查询,是可以使用索引的。
等等,无论是分组,还是排序都是用叶子节点按顺序排序原理。
回表代价
索引文章中讲过,如果使用二级索引,回有回表操作。如果数据多的话,想一想,需要通过聚簇索引查出每一条的完整数据。
覆盖索引:你所查询的字段,刚刚好是联合索引的那几个字段,这样mysql在查询的时候就不会去回表查询,因为联合索引中的叶子节点就已经包含了所需的字段信息。
如果查询数据超过了全部数据的90%,那样就没有必要去使用索引了,因为90%的数据,全部回表,性能消耗很大,还不如直接在聚簇索引中遍历整个表。