MySQL多列索引

多列索引(Multiple-Column Indexes)也称为复合索引(composite index),也即同时对多个列建立索引。


那么问题来了,建立多列索引后,例如建立索引(a, b, c),那么单独对a或者b或者c进行查询,会走索引这条路线吗?

答案是:根据最左前缀原则,也就是对a或者(a,b)或者(a, b, c)查询会用到索引,但以b或者c来查询而不加上a则不会走索引,mysql文档对此有比较完整的例子,可以看一下。说原则是没错,但为什么是这样,这就得追溯到如何实现多列索引的问题。


在mysql文档中并没有相关说明,但经过一番google之后,有篇博文提到了这个问题,在Quora中也有人提出了类似的问题:对于多列索引,mysql会先按照多列索引定义的顺序来连接成一个“新的索引键”,然后据此建立一个B+树,因此,最左前缀原则也得到解释,当查询只出现前几个列来作为查询时,可以通过B+树得到以这个前缀开头的列,由于B+树中的值是排序的,因此接下来就是你要的值,问题就得到解决了。但如果没有以第一个列开头的话,是无法找到索引入口的。


那么,问题又来了,当没有多列索引时,只使用多个单列索引时,这些单列索引是否会起作用?

答案是:具体问题具体分析,在mysql中有种 index merge optimization 技术,暂且翻译为索引归并优化技术吧~ 当索引查询满足一定条件的时候(mysql文档有详细说明,我这里就不重复了),mysql是可以利用索引来查询的,但总体的做法无非就是:先通过这多个列的索引分别得到索引结果,然后再根据相应的索引归并优化算法进行归并。从这也不难看出,但这显然就不是很直接,而且索引归并优化算法也并不总是像你想的那样优化(The Optimization That (Often) Isn’t: Index Merge Intersection),因此还是那句话,具体问题具体分析。下面就来具体看个案例,该案例改编自stackoverflow上的提问:


假设你现在有张表,简化为之后有列userID和postDate,你每次查询时,需要返回某个具体user的所有发表文章,并且是以发表时间降序方式返回,即最新发表的在前,之前发表的在后,这时由于频繁地使用排序,自然希望能够建立个索引提高效率,正如被采纳的回答那样,如果使用多个单列索引,则查询中并没有用到postDate的索引,所以之后还需要进行一个排序,而如果采用多列索引,由于B+树已经是有序的,因此返回的结果已经是有序的,不需要再进行一次排序,所以在这个问题中选择多列索引为优,这里面有个很重要的技巧,用mysql Explain来得到mysql的执行计划,这种分析方法很值得掌握!

你可能感兴趣的:(database)