索引的选择与Change Buffer

1. 索引选择与Change Buffer

问题引出:普通索引 vs 唯一索引 ——如何选择?

在实际业务中,如果一个字段的值天然具有唯一性(如身份证号),并且业务代码已确保无重复写入,那就存在两种选择:

  • 创建唯一索引
  • 创建普通索引

虽然逻辑上两者都可以正确工作,但从 性能角度看,应该如何选择呢?

1.1. 查询场景下的性能差异

查询语句示例:

SELECT name FROM CUser WHERE id_card = 'xxxxxxxyyyyyyzzzzz';

查询过程分析:

  • InnoDB 使用 B+ 树索引,查找过程是按层遍历到叶子节点。
  • 普通索引

找到首个满足条件的记录后,还会继续查找,直到条件不再满足。

  • 唯一索引

找到首个满足条件的记录后立即停止。

性能差距分析:

  • InnoDB 是按数据页(默认16KB)为单位读取的。
  • 也就是说,命中一条记录时,整个数据页已在内存中
  • 普通索引多做一次判断和指针移动,性能开销极小,可以忽略不计。

结论:查询性能差异微乎其微

1.2. 更新场景下的性能差异 (关注 Change Buffer )

Change Buffer 的概念:

  • 又称 变更缓冲区,用于缓存针对尚未加载入内存的数据页的 DML 操作。
  • 目的是延迟磁盘读写,提升写性能。
  • 持久化存储,内存+磁盘双存储。

Merge 操作:

  • 当数据页被访问或系统后台线程定期触发时,change buffer 会被合并(merge)到实际数据页中。

两种索引对比:

特性

唯一索引

普通索引

查询性能差距

几乎无

几乎无

是否能使用 Change Buffer

❌ 不能使用

✅ 可以使用

写入磁盘前是否需加载数据页

✅ 是

❌ 否

写多读少场景优化空间

⛔️ 受限

✅ 提升明显

建议使用场景

严格校验唯一性

默认首选

  • 唯一索引需验证是否存在重复值,必须读入数据页判断唯一性,无法延迟IO。
  • 而普通索引可以直接缓存写操作,延迟数据页加载。

1.3. Change Buffer 的影响和适用场景

Change Buffer 的实际影响分析

1. 情况一:目标页在内存中

  • 唯一索引:读内存判断唯一性后插入,结束。
  • 普通索引:直接插入,结束。
  • ✅ 性能差异极小

2. 情况二:目标页不在内存中

  • 唯一索引:

需要将目标页从磁盘加载入内存进行唯一性判断 → 高成本的随机 IO

  • 普通索引:

操作直接写入 Change Buffer,延迟磁盘读写 → 性能提升明显

这是唯一索引与普通索引的性能关键差异点!

Change Buffer 的适用场景

适用场景 :

  • 写多读少 的系统
    例如:日志系统、账单系统等
    页面写完之后很少会被立即查询,Change Buffer 能发挥显著优势。

不适用场景 :

  • 写后立刻读 的业务模型

写操作刚缓存就被查询命中,触发 merge,反而增加了维护成本。

实际应用建议

  • 查询性能差异不大,但更新性能差异明显
  • 尽量优先选择普通索引,除非业务逻辑依赖数据库强一致性校验。
  • 写多读少场景下,配合开启 Change Buffer(默认开启),显著优化性能。
  • 使用机械硬盘时,Change Buffer 的效果更明显,应适当调大 innodb_change_buffer_max_size 参数(如 50%)
  • 若写后即读,可以考虑 关闭 Change Buffer

2. MySQL选错索引问题分析

2.1. 索引错选问题

问题背景与现象:

  • 有时 MySQL 执行 SQL 时并没有选择最佳索引,导致性能下降。
  • 通过一个具体例子说明了优化器因估算错误而选错索引的情况。

实验设计:

1. 表结构与索引

CREATE TABLE t (a INT,b INT,c INT,INDEX(a),INDEX(b)
);

2. 数据插入

  • 插入数据:(1,1,1)(100000,100000,100000) 共 10 万行。

预期查询语句

SELECT * FROM t WHERE a BETWEEN 10000 AND 20000;

3. 实验步骤(关键触发逻辑)

  • Session A:开启事务,未提交;
  • Session B:

删除所有数据;

重新插入 10 万行;

执行上面的查询。

4. 异常现象

  • 查询变慢,发现 优化器选择了全表扫描 而不是走 a 的索引。

执行计划对比与影响分析:

Q1:默认语句

SELECT * FROM t WHERE a BETWEEN 10000 AND 20000;
  • 使用了全表扫描,rows = 104620
  • 扫描耗时约 40ms

Q2:强制使用索引

SELECT * FROM t FORCE INDEX(a) WHERE a BETWEEN 10000 AND 20000;
  • 使用索引 arows = 10001
  • 扫描耗时约 21ms
  • 结论:Q2 明显更优

2.2. MySQL 优化器选错索引原因

优化器目标

  • 找出 执行代价最小 的执行计划;
  • 代价估算核心:行数(row estimate) + 回表成本

行数估算依赖“统计信息”

  • MySQL 使用索引的基数(cardinality) 估算结果行数;
  • 采样得出,不一定准确;
  • 命令查看基数:
SHOW INDEX FROM t;

统计信息采样机制

  • 参数 innodb_stats_persistent

ON:采样页数 20,触发更新阈值 10

OFF:采样页数 8,触发更新阈值 16

  • 采样带来的估算误差:

优化器以为 a between 10000 and 20000 会返回约 37000 行;

实际只有 10001 行,高估了结果量

回表代价高估

  • 索引 a 是二级索引,取出数据后需要回主键索引查全行(回表);
  • 优化器认为:

37000 次回表 ≈ 37000 次随机 IO;

而全表扫描只需约 100 页顺序读;

所以选择全表扫描。

2.3. 验证与解决方案

观察 EXPLAIN 输出

EXPLAIN SELECT * FROM t WHERE a BETWEEN 10000 AND 20000;
  • rows ≈ 37116(高估)→ 优化器认为成本更高。

修复手段:更新统计信息

ANALYZE TABLE t;
  • 执行后重新 EXPLAIN,rows 变为 10001;
  • 优化器重新选择正确索引。

总结与实践建议

类别

内容

问题核心

优化器因统计信息误差、高估回表代价,选错了索引

典型表现

EXPLAIN 中 rows

显著高估;执行计划走了全表扫描

核心原因

索引基数估算不准确;二级索引导致回表开销被放大

解决办法

使用 ANALYZE TABLE

更新统计信息

实践建议

当发现慢查询/rows 异常时,第一步先做统计更新;必要时使用 force index

临时规避

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/83037.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lua注意事项

感觉是lua的一大坑啊,它还不如函数内部就局部变量呢 注意函数等内部,全部给加上local得了

【多线程初阶】死锁的产生 如何避免死锁

文章目录 关于死锁一.死锁的三种情况1.一个线程,一把锁,连续多次加锁2.两个线程,两把锁3.N个线程,M把锁 --哲学家就餐问题 二.如何避免死锁死锁是如何构成的(四个必要条件)打破死锁 三.死锁小结 关于死锁 一.死锁的三种情况 1.一个线程,一把锁,连续多次加锁 -->由synchroni…

【NLP基础知识系列课程-Tokenizer的前世今生第二课】NLP 中的 Tokenizer 技术发展史

从词表到子词:Tokenizer 的“进化树” 我们常说“语言模型是理解人类语言的工具”,但事实上,模型能不能“理解”,关键要看它接收到了什么样的输入。而 Tokenizer,就是这一输入阶段的设计者。 在 NLP 的发展历程中&am…

Rust 学习笔记:循环和迭代器的性能比较

Rust 学习笔记:循环和迭代器的性能比较 Rust 学习笔记:循环和迭代器的性能比较示例 1示例 2总结 Rust 学习笔记:循环和迭代器的性能比较 示例 1 我们运行一个基准测试,将《福尔摩斯探案集》的全部内容加载到一个字符串中&#x…

pod创建和控制

一、引言 ‌主题‌:pod以及控制器模式中的Deployment作用。‌控制器模式:使用一种API对象(如Deployment)管理另一种API对象(如Pod)的方式。 二、容器镜像与配置文件 ‌容器镜像‌:应用开发者…

HTML实战:爱心图的实现

设计思路 使用纯CSS创建多种风格的爱心 添加平滑的动画效果 实现交互式爱心生成器 响应式设计适应不同设备 优雅的UI布局和色彩方案 <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8"> <meta nam…

2022年 中国商务年鉴(excel电子表格版)

2022年 中国商务年鉴&#xff08;excel电子表格版&#xff09;.ziphttps://download.csdn.net/download/2401_84585615/89772883 https://download.csdn.net/download/2401_84585615/89772883 《中国商务年鉴2022》是由商务部国际贸易经济合作研究院主办的年度统计资料&#xf…

Redis核心数据结构操作指南:字符串、哈希、列表详解

注&#xff1a;此为苍穹外卖学习笔记 Redis作为高性能的键值数据库&#xff0c;其核心价值来自于丰富的数据结构支持。本文将深入解析字符串&#xff08;String&#xff09;、哈希&#xff08;Hash&#xff09;、**列表&#xff08;List&#xff09;**三大基础结构的操作命令&…

如何以 9 种方式将照片从 iPhone 传输到笔记本电脑

您的 iPhone 可能充满了以照片和视频形式捕捉的珍贵回忆。无论您是想备份它们、在更大的屏幕上编辑它们&#xff0c;还是只是释放设备上的空间&#xff0c;您都需要将照片从 iPhone 传输到笔记本电脑。幸运的是&#xff0c;有 9 种方便的方法可供使用&#xff0c;同时满足 Wind…

如何使用Python从MySQL数据库导出表结构到Word文档

在开发和维护数据库的过程中&#xff0c;能够快速且准确地获取表结构信息是至关重要的。本文将向您展示一种简单而有效的方法&#xff0c;利用Python脚本从MySQL数据库中提取指定表的结构信息&#xff0c;并将其导出为格式化的Word文档。此方法不仅提高了工作效率&#xff0c;还…

写作-- 复合句练习

文章目录 练习 11. 家庭的支持和老师的指导对学生的学术成功有积极影响。2. 缺乏准备和未能适应通常会导致在挑战性情境中的糟糕表现。3. 吃垃圾食品和忽视锻炼可能导致严重的健康问题,因此人们应注重保持均衡的生活方式。4. 昨天的大雨导致街道洪水泛滥,因此居民们迁往高地以…

QT使用说明

QT环境准备 推荐Ubuntu平台上使用&#xff0c;配置简单&#xff0c;坑少。 Ubuntu 20.04 安装 sudo apt-get install qt5-default -y sudo apt-get install qtcreator -y sudo apt-get install -y libclang-common-8-dev启动 qtcreatorHelloWorld 打开 Qt Creator。选择 …

React 第四十九节 Router中useNavigation的具体使用详解及注意事项

前言 useNavigation 是 React Router 中一个强大的钩子&#xff0c;用于获取当前页面导航的状态信息。 它可以帮助开发者根据导航状态优化用户体验&#xff0c;如显示加载指示器、防止重复提交等。 一、useNavigation核心用途 检测导航状态&#xff1a;判断当前是否正在进行…

列表单独展开收起同时关闭其余子项的问题优化

如图所示&#xff0c;当在列表中&#xff0c;需要分别单独点开子选项时&#xff0c;直接这样用一个index参数判断即可&#xff0c;非常简单方便&#xff0c;只需要满足点开当前index,然后想同index用null值自动关闭即可

WPF【11_5】WPF实战-重构与美化(MVVM 实战)

11-10 【重构】创建视图模型&#xff0c;显示客户列表 正式进入 MVVM 架构的代码实战。在之前的课程中&#xff0c; Model 和 View 这部分的代码重构实际上已经完成了。 Model 就是在 Models 文件夹中看到的两个文件&#xff0c; Customer 和 Appointment。 而 View 则是所有与…

LangChain-结合魔塔社区modelscope的embeddings实现搜索

首先要安装modelscope pip install modelscope 安装完成后测试 from langchain_community.embeddings import ModelScopeEmbeddingsembeddings ModelScopeEmbeddings(model_id"iic/nlp_gte_sentence-embedding_chinese-base")text "这是一个测试句子"…

可定制化货代管理系统,适应不同业务模式需求!

在全球化贸易的浪潮下&#xff0c;货运代理行业扮演着至关重要的角色。然而&#xff0c;随着市场竞争的日益激烈&#xff0c;货代企业面临着越来越多的挑战&#xff1a;客户需求多样化、业务流程复杂化、运营成本上升、利润空间压缩……这些挑战迫使货代企业不断寻求创新和突破…

Lyra学习笔记2 GFA_AddComponents与ULyraPlayerSpawningManagerComponent

目录 前言GameFeatureAction_AddComponentsULyraPlayerSpawningManagerComponent缓存所有PlayerStart位置选择位置 前言 1.以control模式为例 2.比较散&#xff0c;想单独拿出一篇梳理下Experience的流程 GameFeatureAction_AddComponents 这部分建议看 《InsideUE5》GameFeatu…

进程生命周期

进程生命周期 Linux是多任务操作系统&#xff0c;系统中的每个进程能够分时复用CPU时间片&#xff0c;通过有效的进程调度策略实现多任务并行执行。进程在被CPU调度运行&#xff0c;等待CPU资源分配以及等待外部事件时会处于不同的状态。进程状态如下&#xff1a; 创建状态&a…

文字转图片的字符画生成工具

软件介绍 今天要介绍的这款软件可以将文字转换成图片的排列形式&#xff0c;非常适合需要将文字图形化的场景&#xff0c;建议有需要的朋友收藏。 软件名称与用途 这款软件名为《字符画大师》&#xff0c;是一款在网吧等场所非常流行的聊天辅助工具&#xff0c;其主要功能就…