MySQL 笔记整理(10) --MySQL为什么有时会选错索引?
笔记记录自林晓斌(丁奇)老师的《MySQL实战45讲》
(本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除)
10) --MySQL为什么有时会选错索引?
MySQL中的一张表上可以支持多个索引的,但是,往往你写SQL语句的时候不会去主动指定使用哪个索引。也就是说,使用哪个索引是由MySQL来确定的。而MySQL有时会选择不恰当的索引,我们举一个例子来说明这种情况。
CREATE TABLE `t` (
`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;
然后向表中插入10万行记录,取值按整数递增,即(1,1,1),(2,2,2),(3,3,3)直到(100000,100000,100000)。我们来分析一条SQL语句:
mysql> select * from t where a between 10000 and 20000;
这条语句很简单,想必你也想到了这条语句会使用索引a,事实上也确实使用了索引a。不过别急,这个例子没有这么简单,我们继续来看:

其中 call idata()是执行mysql的存储过程,用来插入数据。需要注意的是,这里Session B就不会再使用索引a了。为了对比结果,可以使用force index(a)来让优化器强制使用索引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*/
- 首先把慢查询日志的阈值设为0,表示这个线程接下来的语句都会进入慢查询日志中。
- Q1是session B原来的查询;
- Q2是seesion B 强制使用索引a的查询。
对比结果如下:

很容易看出第一行查询了10w行,并没有利用到索引a。为什么会这样的,我们从优化器的逻辑谈起
优化器的逻辑:
优化器选择索引的目的,是找到一个最优的执行方案,并用最小的代价去执行语句。在数据库中,扫描行数是影响执行代价的因素之一。我们的优化器就是在判断扫描行数的时候出了问题。那么问题就是,扫描行数是怎么判断的呢?而在真正的执行语句之前,并不能精确地知道满足这个条件的记录有多少条。而只能根据统计信息来进行估算。这个统计信息就是索引的“区分度”。显然,一个索引上不同的值越多,这个索引的区分度就越好,而一个索引上不同值的个数,我们也称之为“基数”(cardinlity)。MySQL是通过采样统计的方式来获得区分度的,统计时时会选择N个数据页来统计。因此这个值是不精确的,当数据表持续变化时,当变更的数据行数超过1/M的时候,会自动触发重新做一次统计。在MySQL中有两种存储索引统计的方式,可以通过参数innodb_stats_persistent的值来进行选择 。
- 设置为on的时候,表示统计信息会持久化存储,默认的M是10,N是20
- 设置为off的时候,表示统计信息值存储在内存中,此时,默认的M是16,N是8.
MySQL选择错误的索引就是因为这个统计信息不准造成的。你可以通过analyze table t命令来进行修正 。
索引的选择异常和处理:
其实大多数时候MySQL的优化器都会选择到正确的索引,但一旦真的发生这种情况,你可以有别的方式来修正。一是刚才提到的,使用force index强行选择一个索引。一旦使用了force index命令,优化器就不会再去评估其他的索引了。但这个方式一来代码不够优雅,二来一旦有索引的改动还需再额外修改代码。第二种方式呢,可以考虑修改语句,引导MySQL使用我们期望的索引。例如在order by相关的语句中,适当调整order by后面跟的条件,可以引导优化器找到正确的索引。三是,在某些场景下,我们可以新建一个更合适的索引。
上期问题:
change buffer一开始是写内存的,那么如果这个时候及其掉电重启,会不会导致change buffer丢失呢?change buffer丢失可不是小事,因为丢失以后就无法再进行merge了,等于是数据丢失了,会不会出现这种情况呢?
答案是不会丢失,虽然只是更新内存,但在事务提交的时候,我们把change buffer的操作也记录到redo log里面去了,所以崩溃的时候change buffer也能找回来。
问题:
本篇前面的例子中,如果没有session A的配合,只是单独执行 delete from t; call idata(); explain这三条语句,会看到explain结果中rows字段其实还是再10000左右,即使用了索引,这是为什么呢?
MySQL 笔记整理(10) --MySQL为什么有时会选错索引?的更多相关文章
- 最全mysql笔记整理
mysql笔记整理 作者:python技术人 博客:https://www.cnblogs.com/lpdeboke Windows服务 -- 启动MySQL net start mysql -- 创 ...
- 10 | MySQL为什么有时候会选错索引?
前面我们介绍过索引,你已经知道了在MySQL中一张表其实是可以支持多个索引的.但是,你写SQL语句的时候,并没有主动指定使用哪个索引.也就是说,使用哪个索引是由MySQL来确定的. 不知道你有没有碰到 ...
- 10 mysql选错索引
10 mysql选错索引 在mysql表中可以支持多个索引,有的sql不指定使用哪个索引,由mysql自己来决定,但是有时候mysql选错了索引,导致执行很慢. 例子 CREATE TABLE `t1 ...
- 深入浅出mysql笔记---1、mysql下载安装
深入浅出mysql笔记---1.mysql下载安装 一.总结 一句话总结: linux下rpm安装即可 1.linux的wget命令作用? 下载文件的工具:比如wget http://cn.wordp ...
- 10 | MySQL为什么有时候会选错索引? 学习记录
<MySQL实战45讲>10 | MySQL为什么有时候会选错索引? 学习记录http://naotu.baidu.com/file/e7c521276650e80fe24584bc9a6 ...
- MySQL选错索引导致的线上慢查询事故
前言 又和大家见面了!又两周过去了,我的云笔记里又多了几篇写了一半的文章草稿.有的是因为质量没有达到预期还准备再加点内容,有的则完全是一个灵感而已,内容完全木有.羡慕很多大佬们,一周能产出五六篇文章, ...
- MySQL 选错索引的原因?
MySQL 中,可以为某张表指定多个索引,但在语句具体执行时,选用哪个索引是由 MySQL 中执行器确定的.那么执行器选择索引的原则是什么,以及会不会出现选错索引的情况呢? 先看这样一个例子: 创建表 ...
- MySQL 笔记整理(17) --如何正确地显示随机消息?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 17) --如何正确地显示随机消息? 如果有这么一个英语单词表,需要每次 ...
- MySQL 笔记整理(1) --基础架构,一条SQL查询语句如何执行
最近在学习林晓斌(丁奇)老师的<MySQL实战45讲>,受益匪浅,做一些笔记整理一下,帮助学习.如果有小伙伴感兴趣的话推荐原版课程,很不错. 1) --基础架构,一条SQL查询语句如何执行 ...
随机推荐
- JavaSE-管道流
1,)创建管道输出流PipedOutputStream pos和管道输入流PipedInputStream pis 2,)将pos和pis匹配,pos.connect(pis); 3,)将pos赋给信 ...
- Win10安装cygwin并添加apt-cyg
1.去Cygwin官网:https://www.cygwin.com/ 进入上图的install链接(下图),根据自己的电脑选择32位还是64位 我选择了一个32位的: 一直下一步下图: 163镜像链 ...
- Android--app性能问题的总结(一)
一个应用程序的性能问题体现在很多方面,app的性能问题,很大程度上决定了使用app的用户量,如果正在使用app的过程中出现app崩溃.卡顿半天加载不出数据(跟网络也有一定的关系).用户请求事件半天获 ...
- 再谈腾讯云centos服务器不能登录的解决过程
上篇文章谈到腾讯云centos服务器不能登录,通过查看监控信息,cpu使用过高,再腾讯云页面使用VNC方式直接登录,然后根据提示信息,关闭导致内存溢出的进程,从而解决问题. 1 问题再现 昨天刚解决了 ...
- ASP.NET Core 实战:基于 Jwt Token 的权限控制全揭露
一.前言 在涉及到后端项目的开发中,如何实现对于用户权限的管控是需要我们首先考虑的,在实际开发过程中,我们可能会运用一些已经成熟的解决方案帮助我们实现这一功能,而在 Grapefruit.VuCore ...
- mysql数据库NO CONNECTION问题分析以及解决方案
自己的站点有时候会挂掉,着实比较麻烦,我不会24小时都看着,说多的都是泪 出现mysql出现NO CONNECTION 有可能原因:mysql服务出现问题 解决方案:重启mysql服务,数据库就连接上 ...
- 死磕 java集合之ArrayBlockingQueue源码分析
问题 (1)ArrayBlockingQueue的实现方式? (2)ArrayBlockingQueue是否需要扩容? (3)ArrayBlockingQueue有什么缺点? 简介 ArrayBloc ...
- Maven把项目依赖的所有jar包都打到同一个jar中
目录 1 使用maven-shade-plugin 2 推荐: 使用maven-assembly-plugin 3 扩展: Maven安装本地jar包到本地仓库 4 扩展: 手动生成jar包 5 扩展 ...
- len(x) 击败 x.len(),从内置函数看 Python 的设计思想
内置函数是 Python 的一大特色,用极简的语法实现很多常用的操作. 它们预先定义在内置命名空间中,开箱即用,所见即所得.Python 被公认是一种新手友好型的语言,这种说法能够成立,内置函数在其中 ...
- java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)
概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...