sql调优的几个关键点

1.explain

主要看的几点:

type  查询级别   

possible_keys   可能用到的索引

key   实际用到的索引

rows   大致扫描行数

extra

其中这个扫描行数只是一个近似行数,并不是实际绝对的扫描行数

MySQL中数据的单位都是页,MySQL又采用了采样统计的方法,采样统计的时候,InnoDB默认会选择N个数据页,统计这些页面上的不同值,得到一个平均值,然后乘以这个索引的页面数,就得到了这个索引的基数。

一般走错索引都是因为优化器在选择的时候发现,走A索引没有额外的代价,比如走B索引并不能直接拿到我们的值,还需要回到主键索引才可以拿到,多了一次回表的过程,这个也是会被优化器考虑进去的。

他发现走A索引不需要回表,没有额外的开销,所有他选错索引

我们可以force index强制走正确的索引

2.缓存问题

在测试环境自己写语句 执行时间可能会受到缓存的干扰,

每次请求的查询语句和结果都会以key-value的形式缓存在内存中的,

如果线上环境缓存失效,就会从磁盘IO获取

缓存失效比较频繁的原因就是 当缓存的表数据被修改,缓存中的整张表都会失效

3.覆盖索引与联合索引

尽量使用覆盖索引,减少一次回表查询

联合索引使用过程中遵循的几个原则保证走索引:
最优作前缀

范围后索引失效

4.普通索引与唯一索引

关键点 change buffer 

当需要更新一个数据页时,如果数据页在内存中就直接更新,尽量避免了把数据页从磁盘读到内存这一步

而如果这个数据页还没有在内存中的话,在不影响数据一致性的前提下,InooDB会将这些更新操作缓存在change buffer中,这样就不需要从磁盘中读入这个数据页了。

在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行change buffer中与这个页有关的操作,通过这种方式就能保证这个数据逻辑的正确性。

将数据从磁盘读入内存涉及随机IO的访问,是数据库里面成本最高的操作之一,change buffer因为减少了随机磁盘访问,所以对更新性能的提升是会很明显的。

将change buffer中的操作应用到原数据页,得到最新结果的过程称为merge。

除了访问这个数据页会触发merge外,系统有后台线程会定期merge。在数据库正常关闭(shutdown)的过程中,也会执行merge操作。

change buffer适用于普通索引,

因为唯一索引的写操作 每次都会把数据页读到内存判断是否违反了唯一性,所以根本不用change buffer

change buffer适用于写多读少的场景

因为merge的时候是真正进行数据更新的时刻,而change buffer的主要目的就是将记录的变更动作缓存下来,所以在一个数据页做merge之前,change buffer记录的变更越多(也就是这个页面上要更新的次数越多),收益就越大。这种业务模型常见的就是账单类、日志类的系统。

假设一个业务的更新模式是写入之后马上会做查询,那么即使满足了条件,将更新先记录在change buffer,但之后由于马上要访问这个数据页,会立即触发merge过程。这样随机访问IO的次数不会减少,反而增加了change buffer的维护代价,所以,对于这种业务模式来说,change buffer反而起到了副作用。

so 得出结论, 建立普通索引还是唯一索引,

首先判断是否需要保证该字段唯一性,

在判断该字段写多读少 就用普通索引,读的频率多 用唯一索引 避免使用change buffer。

5.前缀索引

因为存在一个磁盘占用的问题,索引选取的越长,占用的磁盘空间就越大,相同的数据页能放下的索引值就越少,搜索的效率也就会越低。

如果要检索的字段很长很长,可以考虑前缀索引,

把字段hash为另外一个字段存起来建立索引,每次校验hash值,hash的索引也不大。通过两次查询,先查到hash值下所有行,再缩小范围找到长字段准确值。

如果要检索的字段前缀区分度不高 可以考虑翻转 或者 截取存成新字段 然后建立索引,

可以采用倒序,或者删减字符串这样的情况去建立我们自己的区分度。

原文地址:https://www.cnblogs.com/ttaall/p/14367115.html