MySQL必知必会——创建高性能索引

63 阅读5分钟

索引优化是对查询性能优化最高效的手段

索引基础

mysql只能高效的使用最左前缀原则

1 索引的类型

索引是在存储引擎层实现的

B树:不同存储引擎用不同的方式使用b树

索引对如下查找有用:1、全值查找 2、匹配最左前缀 3、匹配列前缀 4、匹配范围值 5、精确匹配第一列,范围匹配第二列 6、只访问索引的查询(覆盖索引

哈希索引:把所有的哈希码存储在索引里,在哈希表里存储指向数据地址的指针,memory显示支持哈希索引,而且支持非唯一哈希索引

哈希表里不存储数据,不排序,不支持部分索引匹配,不支持范围查询

innodb中有自适应哈希索引,会在b树上创建一个哈希索引。

可以创建自定义哈希索引,在where的时候要手动加上哈希函数。但也要加常量值。

最好不用SHA1和MD5,因为计算出来的很长,可以使用截断计算出来的值

全文索引:查找文本中的关键词

索引的优点

减少扫描的数据量

避免排序和临时表

随机IO改为顺序IO

高性能索引的策略

独立的列

索引列不能是表达式一部分或者是参数

前缀索引和索引选择性

前缀索引会降低索引的选择性,选择性是不重复的索引值与表列总数的比值,对于bolb和text还有较长的varchar类型的数据必须使用前缀索引。

选择前缀数目的方法就是比较和完整列的选择性的大小

无法使用前缀扫描进行order by和group by,也无法使用前缀索引进行覆盖扫描

多列索引

查询能把两个单列索引进行扫描,然后合并,extra那里会出现using union,这是or,and是intersection。

一般出现这种索引合并操作,说明要优化索引了。这种情况下成本会被低估,因为优化器不会把在算法缓存排序合并的资源算到查询成本里。

可以用optimizer_switch来关闭索引合并功能。

选择合适的索引列顺序

可以使用选择性高的列作为索引第一列

聚簇索引

innodb的b+树结构

innodb只聚集一个页里的数据,包含相邻键值的页与页之间可能会相隔很远

聚簇索引也有很多缺点:

1、如果数据都放到内存里,聚簇索引就没啥用了

2、插入的速度完全依赖插入的顺序

3、更新聚簇索引代价高,因为会强制把更新的行移动到指定的位置

4、插入新行的时候可能会导致页分裂

5、可能会导致全表扫描变慢

6、二级索引可能会很大

7、二级索引需要两次索引查找

聚簇索引每个叶子节点包括主键值、事务id、用于事务和MVCC的回滚指针以及剩下列

高并发的时候,顺序主键会引起争用。

延迟关联,可以结合全表查询和覆盖查询,在存在like的情况下,因为索引没法处理like,但是子查询会带来成本问题,所以不一定会提高效率

只有在一个表上才可以。

通常order by用索引排序要遵循最左前缀原则,但是这种情况下可以不用,就是索引第一个被设为常量值。

myisam默认只压缩字符串。

压缩是依赖前面的值,在节省空间的同时查询也会变慢

索引越多插入速度会变慢

innodb在访问行的时候才加锁,索引能减少访问行的次数,所以就能减少锁。

索引案例学习

1 支持多种过滤条件

为了满足最左前缀原则,可以把一些不常用的字段放在索引前面,然后在不需要他的时候用set in技术

2 避免多个范围条件

Explain 用range代表范围查询和列表查询,很难从这里判断。

但列表查询视为多个等值查询,根据最左前缀,后面可以用索引。

3 优化排序

维护索引和表

有三个目的:找到并修复损坏的表、维护准确的索引统计信息、减少碎片。

1 找到并修复损坏的表

用check table来查找

用repair table来修复

innodb表出现损坏后可以通过设置innodb_force_recovery进入innodb的强制恢复模式来修复数据。

2 更新索引统计信息

查询优化器通过两个API来统计:

1、record_in_range,myisam返回的是准确值,innodb返回的是估算值。

2、info()

可以通过analyse table来重新统计索引信息

memory不统计

myisam把信息存储在磁盘里,analyse table的时候需要进行全索引扫描,需要锁表

innodb在5.0之前也不在磁盘存储索引信息,而是随机访问索引进行评估然后存储在内存里。

Show index from可以查索引的基数,基数是指存储引擎估算该索引有多少不同的取值。可以通过information_schema.statistics表来查询这些信息。

innodb通过抽样来统计索引信息,通过innodb_stats_sample_pages来设置样本页的数量。

3 减少索引和数据的碎片

碎片化的索引会以无序或者很差的情况存储在磁盘里

b树的随机访问磁盘是无法避免的

有三种数据的碎片情况:

1、行碎片:数据行存储在多个地方的多个片段中

2、行间碎片:逻辑上顺序的页或者行在磁盘上不是顺序存储的

3、剩余空间碎片:数据页有大量空余空间

innodb不会出现短小的行碎片,innodb会移动短小的行重写到一个片段中。

可以执行optimize table或者导出再导入的方法来重新整理数据。innodb可以先删除索引再创建索引来消除碎片化。