/* mysql扫描行数是如何判断的? mysql在真正的执行语句以前是不知道扫描行数的,只能根据统计信息来估算记录数 这个统计信息就是 区分度 ,显然一个索引上不一样的值越多,这个索引的区分度就越好,而一个索引上不一样值的个数,咱们称之为 基数 ,也就是说这个基数越大,索引的区分度越好 咱们可使用 show index 方法,查看一个索引的基数,如: show index from t 查看t表的索引基数 那么mysql是怎么获取基数的呢?(采样统计) 为何要采样统计呢?由于一张表一行一行查出来精确统计,成本过高 采样统计的时候,innodb是选择n个数据页,统计这些页面上的不一样值,取得一个平均数,而后乘以这个索引的页数,就会的获得这个索引的基数 数据表中的数据是随时发生改变的因此这个基数也会改变因此,当变动的数据行数大于 1/M的时候会自动触发从新作一次索引统计 在mysql中有两种存储索引统计的方式,能够经过设置参数 innodb_stats_persistent的值来选择 设置为on的时候,表示统计信息会持久化存储,这时N默认是20,M是10 设置为OFF的时候,统计信息只存储在内存中,这时N是8,M是16 因为是采样统计,因此N是 20 仍是8 ,这个基数都是很容易不许的 除了扫描行数的不许以外,还有优化器会选择成本低的执行方式,成本低不仅是扫描行数少。 如:一张表有10万条数据,id索引和a索引,使用id索引须要扫描10row 而经过a索引须要15000 row 可是,使用a索引这里须要进行再一次的回表,优化器将这个成本也算进去了,而id是直接在id主键上进行的扫描,没有额外的代价 统计信息不对 修正 analyze table 表名 若是经过explain 这个命令查看的row 和实际相差比较大,就可使用这个命令修正(从新采样统计) 强制使用指定索引( force index(索引名) ) select * from t force index(a) where a between 10000 and 20000; 索引选择异常和处理 1.经过force index 强行使用指定索引 2.修改表结构,引导优化器使用咱们想要的索引 3,在合适的产景下能够考虑添加一个合适的索引来使用 */