1. 复现例子.
2.例子对应的是不断删除历史数据, 然后insert新数据的场景.
1.优化器的逻辑:
1.优化器的目的: 找到一个最优的执行方案
2.最优判断方式: 扫描行数, 是否使用临时表, 是否排序.
3.扫描行数是如何判断的 ?
1.根据统计信息估算
统计信息==> 索引的区分度
索引上不同值的个数 ==> 基数
==> 基数越大,区分度越高
==> show index 可以看到基数. cardinality
注意: 实际上基数都应该是10万,
1 show index 4.mysql是怎么得到索引基数的?
1. 采样统计: 因为全表扫描代价大.
基数 ==> 默认选择N个数据页, 统计页上的不同值, 得到一个平均值, 乘以这个索引的页面数.
因为数据表会持续更新 ==> 当变更的数据行数超过1/ M的时候, 触发一次索引统计.
两种存储索引统计的方式 : innodb_stats_persistent
==> on ==> 持久化 N=20, M10
==> off ==> 内存 N=8 M=16
5.索引统计只是入参, Mysql需判断SQL语句本身要扫描多少行.
5,意外的 expalin 结果疑问2: 为什么放着row 30000+的不用, 用100000+的执行计划呢?
答: 因为回表的时间优化器也计算在内
==> 推断1: 主键索引比普通索引优先级高.
疑问3 : 为什么会得到错误的扫描行数 ?
6.解决统计信息错误 => analyze table t;
6 analyze table t 后, explain2.索引选择异常和处理
1.解决方案1 : force index ==> 硬编码;
2. 修改SQL 引导Mysql
3.新建一个索引, 或者 删除误用索引.
==> 推论3: 对于优化器来说: 索引统计, 排序,使用临时表是有同等权重的. (看源码把)
网友评论