MySQL45讲之优化器选错索引

前言

本文简要介绍了优化器选择索引的依据,以及如何人为地引导优化器选择较好的执行方案。

[En]

This paper briefly introduces the basis for the optimizer to select the index and the ways to artificially guide the optimizer to choose a better execution scheme.

为什么会出现选错索引

可能是统计索引基数信息错误,导致优化器错选索引,也可能是 MySQLbug

选择依据

优化器根据扫描的行记录的数量、返回表的次数、是否创建临时表以及是否对其进行排序来选择索引。

[En]

The optimizer selects the index based on the number of scanned row records, the number of times the table is returned, whether to create a temporary table, and whether to sort it.

索引扫描行数。通过取样的方式统计索引列上不同的值数量,取 N张数据页,统计页面上不同值的数量,然后估算总的不同数量(基数 cardinality),这也称之为索引的”区分度”。可以通过 SHOW INDEX FROM table_name来查看每个索引的基数。

对于这条执行语句 SELECT * FROM t WHERE a BETWEEN (1, 10000) AND b BETWEEN (50000, 100000) ORDER BY b LIMIT 1,从扫描行数上考虑,应该选择 a上的索引,但通过 MySQL执行计划发现,实际选择了 b索引。因为优化器考虑了需要根据 b排序,选择 b索引扫描获取记录可以避免再排序。但是,使用 a索引的查询耗时远比使用 b索引耗时低。

如何避免选错索引

1、强制使用索引

使用 force Index(a)强制 SQL执行时采用某个索引,比如 SELECT * FROM t force Index(a) WHERE a BETWEEN (1, 10000) AND b BETWEEN (50000, 100000) ORDER BY b LIMIT 1

2、重新计算基数

因为 MySQL取样估计基数可能存在比较大的误差,导致优化器选择低效的执行方案。为了避免这个统计信息的问题,可以使用 Analyze TABLE t来重新统计信息。

3、选择更合适的索引或者删除误用的索引

提问

表结构
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;
创建过程,插入 100000 条数据
delimiter ;;
create procedure idata()
begin
  declare i int;
  set i=1;
  while(i

MySQL45讲之优化器选错索引

如果在执行事务 B之前不开启事务 A,那么语句 explain select * from t where a between 10000 and 20000;扫描行数约为 10000行;当开启事务 A,则扫描行数约为 37000行,这是为什么呢?

解释:
不开启事务 A扫描行数为 10000行,因为 MySQL采用的是标记删除的方法,在 purge线程还未执行之前,索引树和表数据并没有清除。当新插入 100000行数据时,因为主键和已经删除的相同,所以会直接复用之前删除的空间,所以优化器抽样判断扫描的行数是 10000行。

开启事务 A扫描行数为 37000行,因为事务 A开启了一致性读,于是新插入数据时,不能复用已经删除的空间,必须开辟新的空间存储,使得索引数据页的数据更加密集,从而优化器抽样判断扫描行数是 37000行。

Original: https://www.cnblogs.com/flowers-bloom/p/select-error-index.html
Author: flowers-bloom
Title: MySQL45讲之优化器选错索引

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/508167/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 第十九章 基于注解的AOP编程

    组装切面 将2 3 4步放在切面类中: 定义切面类: @Aspect 定义额外功能: @Around 原始方法的运行: ProceedingJoinPoint.proceed() …

    数据库 2023年6月14日
    087
  • 2_JDBC

    使用客户端工具访问数据库, 需要手工建立连接, 输入用户名和密码登陆, 编写SQL语句, 点击执行, 查看操作结果(结果集或受行数影响) 在实际开发中, 当用户的数据发生改变时, …

    数据库 2023年6月11日
    064
  • Springboot学习笔记(一)—— 安装

    springboot越来越流行了,相比较于springMVC,springboot采用了一种约定大于配置的理念,可以一键安装,一键运行,一键部署,内置tomcat,省去了一大堆配置…

    数据库 2023年6月9日
    0103
  • MySQL索引分类及相关概念辨析

    本文链接:https://www.cnblogs.com/ibigboy/p/16198243.html 之前的一篇《MySQL索引底层数据结构及原理深入分析》很受读者欢迎,成功地…

    数据库 2023年6月11日
    0102
  • 2022-8-23 css

    ✏️CSS 一个标签可以有多个css样式浏览器处理冲突的能力,如果一个属性通过两个相同的选择器设置到这个元素上,会根据样式的层叠规则样式的层叠规则——按照样式的声明顺序来层叠的【就…

    数据库 2023年6月14日
    073
  • Spring(五)-Spring的其他知识点

    1、细说ServletContext、WebApplicationContext、Servlet的初始化 参考博客–>细说ServletContext、WebAp…

    数据库 2023年6月16日
    0106
  • LeetCode 344. 反转字符串

    编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 //输入一个字符串,输出它的倒序字符串 input: Hello output: olleH …

    数据库 2023年6月11日
    086
  • Dubbo源码(五)-服务目录

    前言 本文基于Dubbo2.6.x版本,中文注释版源码已上传github:xiaoguyu/dubbo 今天,来聊聊Dubbo的 服务目录(Directory)。下面是官方文档对服…

    数据库 2023年6月11日
    0106
  • 2. 函数

    404. 抱歉,您访问的资源不存在。 可能是URL不正确,或者对应的内容已经被删除,或者处于隐私状态。 [En] It may be that the URL is incorre…

    数据库 2023年5月24日
    089
  • 在CentOS 7系统安装StoneDB数据库

    今天我会进行StoneDB数据库在CentOS 7系统下的安装。 在官方的快速部署文档中有详细的安装流程,我会严格遵循流程。 [En] There is a detailed in…

    数据库 2023年5月24日
    093
  • 银河麒麟V10安装MySQL8028

    记一次成功安装MySQL8028到银河麒麟V10,并实现远程访问的方法 工具/原料 数据库下载地址(实验版如图): [En] Download address of the dat…

    数据库 2023年5月24日
    093
  • 数据库持久化+JDBC数据库连接

    数据持久化就是 将内存中的数据模型转换为存储模型,以及 将存储模型转换为内存中的数据模型的统称。数据模型可以是任何数据结构或对象模型,存储模型可以是关系模型、XML、二进制流等。 …

    数据库 2023年5月24日
    078
  • MySQL的插入性能优化

    MySQL的插入性能优化 修改系统变量的方法 一、通过编辑ini配置文件进行修改; 二、通过输入sql命令进行修改; 查询和修改系统变量; 如果要修改全局变量, 必须要显示指定&#…

    数据库 2023年6月14日
    095
  • MySQL专题1: 字段和索引

    MySQL中存在 float, double 等非标准数据类型, 也有 decimal 这种标准数据类型 其区别在于: float, double等非标准类型在DB中保存的是近似值…

    数据库 2023年5月24日
    093
  • Read View的可见性判断理解

    读了 @SnailMann大佬【MySQL笔记】正确的理解MySQL的MVCC及实现原理 收益颇丰,非常感谢! 但对其中如何判断事务是否可见性还是不太理解,于是作了本文,在原博客基…

    数据库 2023年6月16日
    083
  • 创建镜像(alpine版)+alpine

    podman用脚本和dockerfile做apache编译安装镜像 1.0安装介质 2.0 特点 2.0 基础命令 3.0 模式 podman用脚本和dockerfile做apac…

    数据库 2023年6月14日
    0104
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球