1 什么是索引
索引是由一个或者多个列组成的排序的数据结构,通过索引可以高效的找到行的指针,然后根据指针提取行数据,避免低效全表扫描
索引的类型
- B-Tree索引
从索引的根节点开始进行搜索。根节点的槽中存放了指向子节点的指针,储存引擎根据这些指针向下层查找。通过比较节点页的值和要查找的值可以找到合适的指针进入下层子节点,这些指针实际上定义了子节点页中的值的上限和下限。最终储存引擎要么是找到对应的值,要么该记录不存在。
可以使用B-Tree索引的查询类型:
假定有个索引由三个月(first_name, last_name, age)组成
1、全值匹配:和索引中的所有列进行匹配,比如
where first_name='yang' and last_name='zhi' and age=20
2、匹配最左前缀:匹配索引列中的前几列,比如
where first_name='yang'
3、匹配列前缀:比如以什么开头
where last_name like 'y%'
4、匹配范围值:比如时间、数值
where age > 20 and age < 30
5、精确匹配某一列并范围匹配另一列
where first_name='yang' and last_name like 'zh%'
6、只访问索引的查询:即“覆盖索引”
select age from table where first_name='yang' and last_name='zhi'
B-Tree索引的限制:
1、如果不是按照索引的最左列开始查找,则无法使用索引,比如
where last_name='zhi',从第二列last_name开始查找,这样无法使用索引
2、不能跳过索引中的列,比如
where first_name='yang' and age=20,跳过了中间的列“last_name”,这样也无法使用索引
3、如果查询中有某个列的范围查询,则其右边的所有列都无法使用索引优化查找,比如
where first_name='yang' and last_name like 'z%' and age=20,中间有like的范围查询,所以后面的age无法使用索引优化
索引列的顺序非常重要!!!
- 哈希索引
只有Memory引擎支持,哈希索引只包含哈希值和行指针,不包括字段值;哈希索引数据不是按照索引值顺序储存的,所以无法用于排序;也不支持部分索引列匹配查找,因为哈希索引使用索引列的全部内容来计算哈希值;哈希索引只支持等值比较;
经验:可以利用哈希索引思想来优化B-Tree对于长字符串值的索引,比如可以把很长的url,取哈希值(CRC32(url))储存到一个列url_crc,然后查询,where url='url' and url_crc = CRC32('url'),这样性能会非常高,为什么要加上url='url'呢?处理哈希冲突
空间数据索引(R-Tree)
比如储存地理GIS位置,目前支持不完善
全文索引
类似ES,如果对全文搜索要求很高,就直接用ES吧~
2 索引的优点
1、大大减少了服务器需要扫描的数据量:如果不用索引则需要全盘扫描;
2、可以帮助服务器避免排序和临时表:因为索引就是有序的,读取数据的时候就已经是排序了,否则排序都是需要建立临时表的;
3、可以将随机I/O变为顺序I/O:按顺序读取数据非常高效,随机I/O代价很昂贵;
3 高性能的索引策略
- 独立的列
查询的条件必须是独立的列,如
where age + 20 > 30
where length(first_name) = 10
条件左边需要计算、函数调用,这样就不是独立的列
- 前缀索引和索引选择性
前缀索引即建立以列的前几个字符作为索引,比如KEY(city(7))
索引选择性:索引值占列中所有值的比重,一般来讲,比重越高越好,比如唯一索引的索引选择性就是1;
- 多列索引
重点:在多个列上建立独立的单列索引大部分情况下并不能提高MySQL的查询性能!!!
多列索引要按照查询的需求来建立,如果只是几个独立的单列索引,系统虽然会使用“索引合并”来优化查询,但也说明这个索引建的很差劲!
4 选择合适的索引列顺序
索引列的顺序非常重要!
通常把选择性高的列放在前面会更好,但是在多列索引的情况,选择性的判断会有点复杂
5 索引的评价:“三星系统”
1、索引讲相关的记录放到一起则获得一星;
2、如果索引中的数据顺序和查找的排列顺序一致则获得二星;
3、如果索引中的列包含了查询中需要的全部列则获得“三星”
网友评论