第十讲 MySQL为什么有时候会选错索引?

news/2024/11/2 10:09:01/

第十讲 MySQL为什么有时候会选错索引?

一、问题引入

在 MySQL 中,索引选择由优化器负责,其目标是以最小代价执行语句,但有时会选错索引,导致执行速度变慢。

二、案例分析

案例一

  1. 建表与数据插入
    • 创建表t,包含idab字段,分别建立主键索引和ab字段的普通索引。
    • 使用存储过程插入 10 万行数据,取值按整数递增。
  2. 初始查询情况
    • 执行select * from t where a between 10000 and 20000;,优化器选择索引a,扫描行数 10001 行,执行情况符合预期。
  3. 数据变更后的问题
    • session A开启事务,session B删除数据后重新插入 10 万行数据。
    • 此时session B再次执行上述查询,未选择索引a,而是走了全表扫描,扫描 10 万行,执行时间 40 毫秒。而使用force index(a)强制使用索引a时,扫描 10001 行,执行 21 毫秒。
  4. 原因分析
    • MySQL 通过索引的 “区分度”(基数)估算扫描行数,基数越大区分度越好,但采样统计方法导致基数不准。
    • 优化器预估使用索引a时每次从索引a取值后要回主键索引查整行数据,计算代价后认为直接扫描主键索引更快,然而实际执行时间表明此选择并非最优。

案例二

  1. 查询语句
    • select * from t where (a between 1 and 1000) and (b between 50000 and 100000) order by b limit 1;
  2. 预期与实际索引选择
    • 从条件分析使用索引a扫描行数少应更快,但优化器选择了索引b,扫描行数预估为 50198 行。
  3. 原因分析
    • 优化器认为使用索引b可避免排序(b本身有序),即使扫描行数多也判定代价更小。

三、索引选择异常的处理方法

1. 使用force index强行选择索引

  • 优点:能直接指定索引,使优化器不再评估其他索引执行代价。
  • 缺点:写法不优美,索引改名时语句需修改,可能不兼容其他数据库,且变更及时性差,通常在问题出现后才修改 SQL 语句添加,测试发布过程不够敏捷。

2. 修改语句引导优化器

  • 例如将order by b limit 1改为order by b,a limit 1,使扫描行数成为影响决策的主要条件,诱导优化器选择索引a。但这种修改需根据数据特征和语句逻辑,不具备通用性。

3. 新建或删除索引

  • 新建更合适索引或删除误用索引,但在某些案例中可能难以找到合适的新增索引方法,也可能出现删除不必要索引后优化器重新选择正确索引的情况。

四、索引统计更新机制及解决索引统计不准确问题

  1. 索引统计方式
    • MySQL 采用采样统计方法,InnoDB 默认选择N个数据页统计不同值取平均值后乘以索引页面数得到基数。当变更数据行数超过1/M时自动触发重新统计。
    • 可通过设置innodb_stats_persistent参数选择统计信息存储方式,on表示持久化存储,默认N = 20M = 10off表示只存储在内存中,默认N = 8M = 16
  2. 解决索引统计不准确问题
    • 使用analyze table命令重新统计索引信息,可解决因索引统计不准确导致的优化器选错索引问题,但优化器还会综合其他因素判断。

五、总结与思考

  1. 优化器可能因索引统计信息不准确或其他因素选错索引,对于索引统计问题可用analyze table解决,对于其他误判情况可采用force index、修改语句或调整索引等方法。

http://www.ppmy.cn/news/1543839.html

相关文章

边缘计算网关在机床数据采集中的应用-天拓四方

随着工业4.0和智能制造的快速发展,机床作为制造业的核心设备,其数据采集与分析对于提升生产效率、保证产品质量、优化加工过程具有重要意义。传统的数据采集方式存在数据传输速度慢、实时性差、数据处理能力有限等问题。为了解决这些问题,边缘…

java控制台打印除法口诀

直接代码&#xff1a; public class DivisionTable {public static void main(String[] args) {for(int i 1; i < 10;i){for(int j 1;j<i;j){String format String.format("%-8s",(i*j)""j""i);System.out.print(format);}System.out.…

二百七十二、Kettle——ClickHouse中增量导入数据重复性统计表数据(1天1次)

一、目的 在数据质量模块&#xff0c;需要对原始数据的重复性进行统计 Hive中原有SQL语句和ClickHouse现有SQL语句很大不同 二、Hive中原有代码 2.1 表结构 --41、八大类基础数据重复性统计表 事件事件资源不需要重复 create table if not exists hurys_db.dwd_data_d…

Chrome与夸克谁更节省系统资源

在当今数字化时代&#xff0c;浏览器已经成为我们日常生活中不可或缺的一部分。无论是工作、学习还是娱乐&#xff0c;我们都依赖于浏览器来访问互联网。然而&#xff0c;不同的浏览器在性能和资源消耗方面存在差异。本文将探讨Chrome和夸克两款浏览器在系统资源消耗方面的表现…

来康生命科技有限公司心率监测解决方案在健身房与康养机构的应用探索

引言 随着科技的日新月异&#xff0c;智能健康服务正逐步成为现代健康管理不可或缺的一环。来康生命科技有限公司&#xff0c;凭借其在智能物联集成交互领域的自主创新能力&#xff0c;推出了一款集蓝牙物联网、蓝牙手环、数据云与管理终端于一体的心率监测解决方案。此方案专…

修改HarmonyOS鸿蒙图标和名字,打包后安装到真机,应用图标丢失变成透明,修改名字也不生效,还是默认的labeL解决方案教程

HarmonyOS鸿蒙打包hap 安装应用到桌面没有图标&#xff0c;用hdc安装到真机&#xff0c;打包后应用图标丢失变成透明&#xff0c;名字也还是默认的label的bug&#xff0c;以下是解决方案 以下是修改方案&#xff1a; 1、修改应用名字&#xff1a; 2、修改应用图标&#xff1a…

C++音视频04:音视频编码、生成图片

视频编码 #include <libavutil/log.h> #include <libavutil/opt.h> #include <libavcodec/avcodec.h>static int encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *out) {int ret -1;ret avcodec_send_frame(ctx, frame);if (ret < …

[数组基础] 0498. 对角线遍历

文章目录 1. 题目链接2. 题目大意3. 示例4. 解题思路5. 参考代码 1. 题目链接 498. 对角线遍历 - 力扣&#xff08;LeetCode&#xff09; 2. 题目大意 描述&#xff1a;给定一个大小为 mn 的矩阵 mat 。 要求&#xff1a;以对角线遍历的顺序&#xff0c;用一个数组返回这个矩…