10 mysql选错索引
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选错索引相关推荐
- mysql选错索引怎么解决_MySQL选错索引的原因以及解决方案
MySQL 中,可以为某张表指定多个索引,但在语句具体执行时,选用哪个索引是由 MySQL 中执行器确定的.那么执行器选择索引的原则是什么,以及会不会出现选错索引的情况呢? 先看这样一个例子: 创建表 ...
- cardinality mysql_Cardinality统计取值不准确导致MYSQL选错索引
场景简介 SQL明明可以走a索引,却走了慢的b索引? 场景模拟use muke; drop table if exists t13; CREATE TABLE `t13` ( `a` int(11) ...
- 《MySQL——选错索引,该如何做》
如果不断地删除历史数据和新增数据,MySQL有时会选错索引. 选择索引是优化器的工作,优化器优化时会考虑的因素:扫描行数.是否需要排序.是否使用临时表 MySQL通过统计索引上的基数,作为索引的区分度 ...
- MySQL选错索引导致的线上慢查询事故复盘
前言 又和大家见面了!又两周过去了,我的云笔记里又多了几篇写了一半的文章草稿.有的是因为质量没有达到预期还准备再加点内容,有的则完全是一个灵感而已,内容完全木有.羡慕很多大佬们,一周能产出五六篇文章, ...
- MySQL优化器选错索引情况
MySQL优化器选错索引情况 1. 优化器选错索引 2. 优化器的逻辑 3. 索引选择异常和处理 1. 优化器选错索引 之前MySQL架构以及执行sql查询语句介绍过MySQL优化器可以帮助我们优化s ...
- mysql explain 为空_车祸现场!我的MySQL千万级数据表选错索引了!
最近在线上环境遇到了一次SQL慢查询引发的数据库故障,影响线上业务.经过排查后,确定原因是:SQL在执行时,MySQL优化器选择了错误的索引(不应该说是"错误",而是选择了实际执行 ...
- mysql为什么选错索引?怎么解决?
mysql为什么选错索引? 在进行慢SQL分析的时候,有时候我们会发现explain的扫描行数和慢日志中的行数相差很大,那explain中的rows这个扫描行数是怎么判断的? 其实MySQL在真正开始 ...
- MySQL MySQL为什么有时候会选错索引?
选错索引的案例 server层优化器的逻辑 主要工作 选择索引 扫描行树判断 选错索引的解决方案 索引选择异常和处理
- db2 删除索引_MySQL 选错索引的原因是什么?
MySQL 中,可以为某张表指定多个索引,但在语句具体执行时,选用哪个索引是由 MySQL 中执行器确定的.那么执行器选择索引的原则是什么,以及会不会出现选错索引的情况呢? 先看这样一个例子: 创建表 ...
最新文章
- pip安装模块警告InsecurePlatformWarning: A true SSLContext object is not available.
- 《kafka中文手册》-快速开始(二)
- linux fdisk等命令,Linux fdisk命令操作磁盘(添加、删除、转换分区等)
- Netty专题-(3)NIO网络编程
- jQuery下的ajax【5分钟掌握】
- 【CentOS 7笔记4】,两种修改密码方式#
- Oracle 大规模 delete,update 操作 注意事项
- hibernate、easyui、struts2整合
- Modularity(模块化-UMD通用模式)
- php和mysql实现图书管理系统_0074 实现图书管理系统的登录、员工和菜单功能
- 矩池云python2.7镜像安装opendr
- Asp.Net客户端触发服务器端事件及_dopostback
- The Art Of Code-Beta
- Gopher协议与ssrf
- 计算机网路课程设计——电子邮件客户端的设计与实现——接收邮件(POP3协议)
- Ceph rgw中的元数据组织形式及存储结构分析
- Java---多线程入门
- ps快速切图,文件命名图片自动导出
- 大吉大利-今晚吃鸡-枪械
- ArcMap关联图层并发布为服务