今天群里有人讨论了这个问提,http://weibo.com/1642466057/yAl6d5Izh
而且更巧的是这个内容是我昨晚看的,但是当时只是记住了一个结论,并没有仔细去研究mysql优化器的原理。
其实这个问题群里说早就有人发现了,可以参考这个Mysql中对primary key一点选择改变http://hidba.org/?p=179
结论就是老版本的 还是会走第一索引。5.1.46 的优化器 才有这个改进
顺便看了下聚簇索引和二级索引的只是看了下,但是越来越发现改进的效果是不是不好啊?我这里只是表达下自己的看法,请轻拍。
我的观点如下:
http://isky000.com/database/innodb_index_structure_basic
http://isky000.com/database/myisam-index-structure
我没有仔细看过索引结构的实现,但是这个是简朝阳的对innodb和myisam的索引树的介绍。
我们就innodb而言,主索引的叶子节点存储了key和整行的数据,而二级索引存储了key和主键,如果像群里的那个结论,使用二级索引,那么取全表的时候就会先取key然后再用主键去取下整行数据,是不是会增加磁盘的IO啊。
这里有个更详细的对比图
http://datalj.blog.163.com/blog/static/342230312012423103049508/
/**
* 20120906 回去看了下innodb那本书
*/
本地做实验,test表就两个字段,id和name,id是主键,name上有一个二级索引
explain确实是发生了没有走主键而走的二级索引
1 SIMPLE test index ind 33 4 Using index
为表添加字段state,在做一次全表查询
这次就木有走索引了,而走的是全表扫描,所以我强烈怀疑微博中提到的数据的准确性。
那么我就再做一个实验,把name和state加上一个联合索引,再做执行
果然如此有走了二级索引
SO....事情的真相如此。。。
对于innodb来说,注意是innodb哦,myisam的索引结构还是另一种情况。
innodb上的二级索引存储的是索引和主键,那么只要扫描一次二级索引就可以取出主键及索引上列的数据,如果这些数据包括了全表的内容,那么mysql优化器会在取全表内容是自动走可以包括所有内容的索引。如果要去取主键的时候,因为主键的索引结构的叶子节点上只有一个主键的值和一个指向全行的指针,那么想取出全行是上的其他数据就还要再去进行一次IO,所以mysql就直接用二级索引喽,当然是在没有where和order的时候
/**
* 20120906
*/
不好意思,微博的数据我粗心了,原来作者的意图不是取全表,而是取主键。。。我之前有点先入为主了。
那我再补充一段测试数据吧,微博的原作者是对的。
这是后表结构的二级索引改成了name
取主键列的话走的是二级索引
取二级索引上的列的时候也走的是二级索引
但是取非主键和非二级索引的时候就要全表了
个人观点是,主键和二级索引都是直接从叶子节点上取,mysql会优先走二级索引上的列。
这里推荐几个资料:
http://knielsen-hq.org/presentations/innodb-clustered-index/innodb-clustered-index.pdf
http://blog.chinaunix.net/uid/26896862.html