10 mysql选错索引

在mysql表中可以支持多个索引,有的sql不指定使用哪个索引,由mysql自己来决定,但是有时候mysql选错了索引,导致执行很慢。

例子

CREATE TABLE `t10` (`id` int(11) NOT NULL,`a` int(11) DEFAULT NULL,`b` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `a` (`a`),KEY `b` (`b`)
) ENGINE=InnoDB;

往表中插入10w记录

过程

delimiter ;;
create procedure idata_t11()
begindeclare i int;set i=1;while(i<=100000)doinsert into t10 values(i, i, i);set i=i+1;end while;
end;;
delimiter ;
call idata_t11();

分析sql语句

mysql> select * from t where a between 10000 and 20000;

SESSION A

SESSION B

start transaction with consistent snapshot;

delete from t;

call idata_t11()

explain  select * from t10 where a between 10000 and 20000;

commit;

 

Session B的查询语句explain  select * from t10 where a between 10000 and 20000;就不会在选择所有a了,可以通过慢查询日志

set long_query_time=0;
select * from t where a between 10000 and 20000; /*Q1*/
select * from t force index(a) where a between 10000 and 20000;/*Q2*/

优化器的逻辑

选择索引是优化器的工作,而优化器选择索引的目的,是找到一个最优的执行方案,并用最小的代价去执行语句

在数据库里面,扫描行数是影响执行代价的因素之一,扫描的行数越少,意味着访问磁盘数据的次数越少,消耗的cpu资源越少。

当然,扫描行数并不是唯一的判断标准,优化器还会结合是否使用临时表、是否排序等因素综合判断。

扫描行数是怎么判断的?

MySQL在真正开始语句执行之前,并不能精确地知道满足这个条件的记录是多少,只能根据统计信息来估算记录数。

这个统计信息就是索引的”区分度”,显然,一个索引上不同的值越多,这个索引的区分度也就越高,而一个索引上不同的值的个数,称为”基数”,这个基数越大越好。

Mysql采样统计的方法,采样统计的时候,innodb默认会选择N个数据页,统计这些页面上的不同值,得到一个平均值,然后乘以这个索引的页面数,就得到了这个索引的基数。

而数据表是会持续更新的,索引统计信息也不会固定不变,所以,当变更的行数超过1/M的时候,会自动触发重新做一次索引统计。

在mysql中,有两种存储索引统计的方式,可以通过参数innodb_stats_persitent

(system@127.0.0.1:3306) [test]> show variables like 'innodb_stats_persistent';
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| innodb_stats_persistent | ON    |
+-------------------------+-------+

--设置为on,表示统计信息会持久化到存储,默认N=20,M=10

--设置为off,表示统计信息只存储在内存中,默认N=8,M=16

其实索引统计只是一个输入,对于一个具体的语句来说,优化器还要判断,执行这个语句要扫描多少行

统计信息不准确,使用analyze table t10;

mysql> explain select * from t where (a between 1 and 1000) and (b between 50000 and 100000) order by b limit 1;

索引选择异常和处理

一种方法是,采用force index(t)强行选择一个索引。

第二种方式就是,可以考虑修改语句,引导mysql使用我们期望的索引。

之前优化器选择使用索引b,因为它认为使用索引b可以避免排序(b本身是索引,已经是有序的,如果选择索引b的话,不需要在做排序只需要遍历),所以即使扫描行数更多,也判定为代价更小。

现在使用了 order by b,a,要求按照b,a排序,就意味着使用这两个索引都需要排序,因此扫描行数变成了影响决策的主要条件,此时就选择了a索引。

当然,这种修改并不是通用的优化手段,只是刚好在这个语句有limit 1,如果都有满足条件的行,要逻辑结果一致才可以这么修改。

第三种是在有些场景下,我们可以新建一个更合适的索引,来提供给优化器做选择,或者删掉误用的索引。

转载于:https://www.cnblogs.com/yhq1314/p/11307175.html

10 mysql选错索引相关推荐

  1. mysql选错索引怎么解决_MySQL选错索引的原因以及解决方案

    MySQL 中,可以为某张表指定多个索引,但在语句具体执行时,选用哪个索引是由 MySQL 中执行器确定的.那么执行器选择索引的原则是什么,以及会不会出现选错索引的情况呢? 先看这样一个例子: 创建表 ...

  2. cardinality mysql_Cardinality统计取值不准确导致MYSQL选错索引

    场景简介 SQL明明可以走a索引,却走了慢的b索引? 场景模拟use muke; drop table if exists t13; CREATE TABLE `t13` ( `a` int(11) ...

  3. 《MySQL——选错索引,该如何做》

    如果不断地删除历史数据和新增数据,MySQL有时会选错索引. 选择索引是优化器的工作,优化器优化时会考虑的因素:扫描行数.是否需要排序.是否使用临时表 MySQL通过统计索引上的基数,作为索引的区分度 ...

  4. MySQL选错索引导致的线上慢查询事故复盘

    前言 又和大家见面了!又两周过去了,我的云笔记里又多了几篇写了一半的文章草稿.有的是因为质量没有达到预期还准备再加点内容,有的则完全是一个灵感而已,内容完全木有.羡慕很多大佬们,一周能产出五六篇文章, ...

  5. MySQL优化器选错索引情况

    MySQL优化器选错索引情况 1. 优化器选错索引 2. 优化器的逻辑 3. 索引选择异常和处理 1. 优化器选错索引 之前MySQL架构以及执行sql查询语句介绍过MySQL优化器可以帮助我们优化s ...

  6. mysql explain 为空_车祸现场!我的MySQL千万级数据表选错索引了!

    最近在线上环境遇到了一次SQL慢查询引发的数据库故障,影响线上业务.经过排查后,确定原因是:SQL在执行时,MySQL优化器选择了错误的索引(不应该说是"错误",而是选择了实际执行 ...

  7. mysql为什么选错索引?怎么解决?

    mysql为什么选错索引? 在进行慢SQL分析的时候,有时候我们会发现explain的扫描行数和慢日志中的行数相差很大,那explain中的rows这个扫描行数是怎么判断的? 其实MySQL在真正开始 ...

  8. MySQL MySQL为什么有时候会选错索引?

    选错索引的案例 server层优化器的逻辑 主要工作 选择索引 扫描行树判断 选错索引的解决方案 索引选择异常和处理

  9. db2 删除索引_MySQL 选错索引的原因是什么?

    MySQL 中,可以为某张表指定多个索引,但在语句具体执行时,选用哪个索引是由 MySQL 中执行器确定的.那么执行器选择索引的原则是什么,以及会不会出现选错索引的情况呢? 先看这样一个例子: 创建表 ...

最新文章

  1. pip安装模块警告InsecurePlatformWarning: A true SSLContext object is not available.
  2. 《kafka中文手册》-快速开始(二)
  3. linux fdisk等命令,Linux fdisk命令操作磁盘(添加、删除、转换分区等)
  4. Netty专题-(3)NIO网络编程
  5. jQuery下的ajax【5分钟掌握】
  6. 【CentOS 7笔记4】,两种修改密码方式#
  7. Oracle 大规模 delete,update 操作 注意事项
  8. hibernate、easyui、struts2整合
  9. Modularity(模块化-UMD通用模式)
  10. php和mysql实现图书管理系统_0074 实现图书管理系统的登录、员工和菜单功能
  11. 矩池云python2.7镜像安装opendr
  12. Asp.Net客户端触发服务器端事件及_dopostback
  13. The Art Of Code-Beta
  14. Gopher协议与ssrf
  15. 计算机网路课程设计——电子邮件客户端的设计与实现——接收邮件(POP3协议)
  16. Ceph rgw中的元数据组织形式及存储结构分析
  17. Java---多线程入门
  18. ps快速切图,文件命名图片自动导出
  19. 大吉大利-今晚吃鸡-枪械
  20. ArcMap关联图层并发布为服务

热门文章

  1. 广度优先搜索算法(Breath-first Search)是如何搜索一张图的?
  2. arcgis for android 无法加载本地jpg影像解决办法
  3. 《云服务器》与《传统服务器》的区别
  4. android微信第三方登录怎么通过code获取openid?
  5. tablesorter,jquery
  6. 从零开始学习OpenWrt完美教程-转
  7. typedef和define的作用域
  8. 【iOS开发】swift 3.0 延长设置launch image启动页面图片显示时间
  9. 直播间搭建项目——延续直播发展趋势
  10. 设计模式之—工厂方法模式