根据主键查找
先建个表
create table student(
id int(11) primary key,
name varchar(50),
place varchar(100),
age int(8)
);
create index idx_name on student(name);
create index idx_age_place on student(age,place);
无索引方式查询
保证数据存放在页中的主键是依次递增的的情况下:
数据页记录上下页地址通过双链表链接,页内数据项纪录下一条数据地址,通过单链表的方式查找,数据量大的情况下效率低下
聚簇索引
聚簇索引是数据库表的主键索引,生成主键默认会生成的的索引。也是唯一一个数据即索引的索引。以B+树的结构存储数据,所有的叶子结点都是真实的数据页,数据页之间链表结构。
目录页中存放的是主键值,B+树一般深度在3-4,数据页中根据主键递增的顺序排下去。简单的计算一下如果数据页中最大允许存放数据项100项,目录页最大允许1000项。
degree = 1,1个数据项
degree = 2,1001000
degree = 3,1001000*1000
根据其他项查找
根据其他项查找的条件下,就要遍历所有页中的数据,比较数据项和查找项。效率远比主键低下,因为主键一般情况下是顺序的,只需要比较页尾的元素,而其他数据项只能从第一页遍历到最后一页。
非聚簇索引
create index idx_name on student(name);
二级索引,以数据库某一项作为索引,如果查找的数据项有该索引和主键外的数据项,需要回表。先根据二级索引查询到主键值,通过主键去聚簇索引中获取数据。查询过程可以注意下覆盖索引
根据多项查找
查询过程中,比如上面的数据表。select * from student where age = ‘10’ and place = ‘3200001’;
简单分析:多个条件的情况下,如果最左项数据有对应的索引,会走该列的二级索引,这个时候还有其他条件,是能从满足的主键中回表,加上条件查找,还不够高效,可以思考一下如果目录页只有到杭州市,你想要查杭州富阳市,这个时候能不能把富阳也跟在目录页上。
联合索引
建立索引的时候先根据age建索引,age相同的情况下根据place排。最合适的使用联合索引的方式是全值匹配,常用的sql查询语句条件项的顺序都能和索引对的上。
以上面的查询为例select * from student where age = ‘10’ and place = ‘3200001’,假设我们把age和place顺序倒置一下,按我们对最左向匹配的规则理解,应该是无法走index_age_place索引的,实际过程中依旧走了(mysql优化器发挥了作用)
但是select * from student where place ='3200001’这样的sql是无法走index_age_place索引的,也很好理解当前索引是根据age先排序的,所以保证age顺序的情况下,place才是顺序的。
不是所有的sql都适合走非聚簇索引的,当非聚簇索引的数据返回占了数据的80%以上时,依旧需要回表走聚簇索引,还不如让sql走聚簇索引,二级索引查询的时候走的是顺序IO,但是回表是随机IO,可以走全表扫描走聚簇索引走顺序IO
唯一索引
建立索引的时候可以声明索引是否是唯一索引,聚簇索引是唯一索引。
唯一索引一定比非唯一索引快吗?
事实上,建立唯一索引,在新增或者编辑字段的时候,额外的需要做一个唯一判断。
索引总结
1.本文讲的主要是查询时候如何选择执行索引,其实排序分组的sql都有可能会走索引
2.建索引是有时间和空间上的消耗的,合理的建立索引
3.减少不必要的索引,和索引冗余
4.可以只对字符串的前缀建立索引,选择索引列尽可能小
5.查询过程中避免在条件中做表达式,破坏索引
6.走全值匹配索引和索引覆盖能有效的提高查询效率