当前位置: 首页 > news >正文

终于有人把MySQL索引讲明白了!(从新手视角看B+树)

文章目录[toc]终于有人把MySQL索引讲明白了(从新手视角看B树)1. 无索引的世界全表扫描2. 索引是什么一张“排好序”的快照为什么MySQL首选B树而不是哈希表3. 灵魂主角深入剖析 B Tree 索引3.1 先理解它的前身二叉查找树3.2 B树的“进化”矮胖子、多路、有序4. 动手画一遍B树的构建与查找5. 聚簇索引 vs 二级索引InnoDB的真实面貌5.1 聚簇索引 (Clustered Index)5.2 二级索引 (Secondary Index)5.3 覆盖索引性能优化的法宝6. 写给新手的“避坑”指南写在最后终于有人把MySQL索引讲明白了(从新手视角看B树)你是否曾面对千万级数据查询慢得像蜗牛而束手无策是否听说过“索引能提高查询速度”但对其背后原理一知半解今天我们不谈高大上的术语从一个初学者的视角出发彻底搞懂MySQL索引尤其是最核心的B Tree索引。1. 无索引的世界全表扫描想象一本1000页的字典里面的字不是按拼音或部首排列的而是乱序的。现在让你找到“獭”字你会怎么做没办法你只能从第一页开始一页一页翻直到找到为止。这就是数据库在没有索引时的操作——全表扫描。-- 假设 users 表有1000万条数据且 name 列没有索引SELECT*FROMusersWHEREname张三;-- 数据库需要逐行检查所有1000万行数据灾难性的查询效率索引就是给数据“排序并建立目录”让你能快速定位。2. 索引是什么一张“排好序”的快照索引在数据库层面是一种排好序的、快速查找的数据结构。它有两个核心目的排序让数据按某种规则有序排列。快速定位利用排好序的特性快速跳过不符合条件的数据。MySQL中最常用的索引数据结构有两种哈希表 (Hash)和B树 (B Tree)。为什么MySQL首选B树而不是哈希表你可能听过哈希表查找速度极快理论上O(1)但为何MySQL的InnoDB引擎默认使用B树场景哈希表B树单值精确查找()极快O(1)稍慢O(log N)范围查找(,,BETWEEN)无能为力因为哈希值不保序极快叶子节点有序且构成链表排序(ORDER BY)完全无序需额外排序数据天然有序直接扫描即可模糊前缀匹配(LIKE abc%)无法使用可以利用有序结构快速定位范围结论日常业务中等值查询、范围查询、排序操作都极其频繁哈希表无法应对范围查询因此B树成为了平衡与效率的最优选。3. 灵魂主角深入剖析 B Tree 索引这才是今天的重头戏。不要被名字吓到我们用图解和类比来把它彻底搞懂。3.1 先理解它的前身二叉查找树一个简单的二叉查找树规则是左子节点 父节点 右子节点。查询时从根节点开始比当前节点小就向左大就向右。效率很高但有个致命问题如果插入的数据恰好是递增的1,2,3,4,5…树会退化成一条斜线链表查找效率瞬间降为O(N)。3.2 B树的“进化”矮胖子、多路、有序为了解决二叉树的退化问题B树做了三层关键进化进化一多路平衡不再“高瘦”B树是一个多叉树一个节点可以存储多个key并且分裂出多个分支这叫“多路”。最关键的是它从叶子到根所有路径等长这叫“平衡”。这让树变得非常“矮胖”。MySQL将一个节点的大小默认设置为16KB刚好一页能装下成百上千个key。哪怕几千万数据B树高度通常也只需要3到4层。3次磁盘I/O就能定位到数据堪称神速。进化二数据只存叶子非叶子只“指路”这是B树与B树的核心区别也是它高效的关键。非叶子节点树枝只存储键值(key)和指向子节点的指针不存储完整行数据。这让一个节点能容纳的索引键数量极大进一步压低了树高度。叶子节点树叶存储完整的索引键值和对应行的数据或数据地址。所有索引信息都在叶子节点上。进化三叶子节点之间有“单向/双向链表”这是一个极其伟大的设计所有叶子节点按照键值顺序首尾相连形成一个有序链表。这就解决了前面说的范围查询痛点。比如要找age 20 and age 30的数据只需先通过树枝定位到age20的叶子然后顺着链表往后扫扫到age30为止完全不用再回上层树枝节点。4. 动手画一遍B树的构建与查找假设我们有这些记录按ID建索引(1,小明) (3,小红) (5,小蓝) (7,小刚) (9,小美)… 设一个非叶子节点最多存2个key(3个指针)叶子节点最多存2条数据。逐步构建过程插入数据插入1,3。放入第一个叶子节点[1,3]。插入5。叶子节点要存1,3,5但上限是2必须分裂。取中间值3升为树枝节点。分裂成左叶[1]右叶[3,5]树枝[3]指向它们。插入7。放入右叶[3,5,7]超限再次分裂。中间值5升到树枝。树枝变为[3,5]指向三个叶子[1],[3],[5,7]。继续插入…树枝节点[3,5]满了之后中间值会继续向上分裂形成更高层。这就是B树自平衡、自下而上分裂生长的过程。查找过程查找ID7第一次磁盘I/O加载根节点树枝节点。检查7与节点中key的大小关系发现它在[5]区间假设节点只存了5通过指针进入右子树。第二次磁盘I/O加载下一层树枝节点。发现7应进入指向[5,7]叶子节点的分支。第三次磁盘I/O加载叶子节点在[5,7]里通过二分查找直接定位到7找到数据。范围查找过程查找 3 ID 9通过树结构快速定位到第一个符合条件的叶子节点即包含3或大于3的节点比如[3]或[5,7]。直接从该叶子节点开始沿着节点间的双向链表指针向后扫描[3]-[5,7]-[9,...]轻松获取范围内所有数据无需再从根节点重新遍历。5. 聚簇索引 vs 二级索引InnoDB的真实面貌这是面试和实际理解中极易混淆的点。5.1 聚簇索引 (Clustered Index)是什么索引的叶子节点直接存储了完整的行数据。数据即索引索引即数据。特性InnoDB中一张表有且仅有一个聚簇索引。默认选择有主键主键就是聚簇索引无主键第一个唯一非空索引都没有InnoDB会生成一个隐藏的6字节row_id作为聚簇索引。意义当你通过主键查询时到达叶子就能直接拿到整行数据极快。5.2 二级索引 (Secondary Index)是什么我们自己创建的普通索引、唯一索引等。它的叶子节点存储的内容不再是完整行数据而是对应的主键值这个主键值就是聚簇索引的key。查询过程——回表比如SELECT * FROM user WHERE name 张三且name列有索引。在name索引树中找到‘张三’这个键取出它对应的主键ID假设是10。拿到ID10后再跑到聚簇索引树里从根节点重新查一遍找到ID10的叶子才拿到整行数据。这个过程就叫回表。多跑了一趟主键索引树。5.3 覆盖索引性能优化的法宝如果能避免回表查询效率会大幅提升。比如查询SELECT id, name FROM user WHERE name 张三。因为name索引树的叶子节点已经存了主键id而你要查的正是id和name所有需要的数据在name索引树上都拿到了无需回表。这就叫覆盖索引Using index。其本质是要查询的列被所使用的索引完全覆盖了。这是SQL优化中最常用、最有效的手段之一。6. 写给新手的“避坑”指南学了原理这些实践原则你才能真正理解并记住为WHERE、ORDER BY、JOIN涉及的列建索引这是基本要求。最左前缀原则联合索引(A,B,C)本质是先按A排序A相同再按B排序…所以它能加速A、A,B、A,B,C的查询但无法跳过A直接用B或C。避免在索引列上做运算或函数WHERE age120会导致索引失效因为树里存的是age的值不是age1的值。应写成WHERE age19。小心隐式类型转换字符串字段用整型查询如WHERE phone13800138000MySQL会对字段做函数转换导致索引失效。一定要加引号WHERE phone13800138000。离散度越高索引效果越好在性别男女这种字段建索引意义不大因为一个值对应几十万行优化器可能认为不如全表扫描。善用慢查询日志和EXPLAIN永远用EXPLAIN SELECT...分析你的查询计划看type至少达到range最好ref/const、key用了哪个索引、Extra是否出现Using filesort, Using temporary这些糟糕的标志。写在最后B树不是一门复杂艰深的计算机科学魔法它是一位思路清晰的图书管理员用多路平衡的结构把书库数据整理得井井有条用目录卡片非叶子节点来快速指路所有书都整齐码放在开架书库叶子节点里并且书架之间还贴心地连上了通道链表。理解了这层逻辑索引就不再是背诵的八股文而成为你进行数据库设计与性能优化的直觉。用多路平衡的结构把书库数据整理得井井有条用目录卡片非叶子节点来快速指路所有书都整齐码放在开架书库叶子节点里并且书架之间还贴心地连上了通道链表。理解了这层逻辑索引就不再是背诵的八股文而成为你进行数据库设计与性能优化的直觉。如果这篇文章让你对B树有了新的认识不妨转给和你一样在数据库之路上摸索的小伙伴。毕竟搞懂索引是跨过“会用SQL”与“真正懂数据库”那道门槛的关键一步。
http://www.gsyq.cn/news/1388972.html

相关文章:

  • 终极RimWorld模组管理实战:3步驯服500+模组依赖混乱
  • 提示词组成工作流重构
  • 密封性好不漏液的PCR八联管品牌推荐 - 品牌推荐大师
  • Qt调用C# DLL的跨运行时桥接实战指南
  • Kerberos核心原理与生产级故障排查实战指南
  • OBS虚拟摄像头终极指南:3分钟让所有视频软件用上专业特效
  • 从主板电池到NTP:深入Linux硬件时钟(RTC)的‘前世今生’与hwclock实战指南
  • 四川全屋定制源头工厂可靠性评测:技术维度全解析 - 奔跑123
  • 3个高级技巧彻底掌握RimSort:从依赖图解析到性能优化
  • 基于事件驱动的智能体调度系统:实现项目自动化协同与DevOps流程优化
  • 四足机器人操作与移动耦合技术解析
  • STM32F767驱动非原厂RGB屏?手把手教你用CubeMX+LTDC+DMA2D搞定(附避坑指南)
  • 差分隐私机器学习评估:构建可靠、泛化的系统性框架
  • Jasminum插件:3步搞定Zotero中文文献管理,科研效率提升10倍
  • Java开发最常用的工具类/实用类详解
  • ARM架构PMSELR寄存器与性能监控实践
  • [智能体-73]:智能体编排核心难点:可复用任务分解落地方法论
  • 三相异步电机调压调速,除了Simulink仿真还能怎么学?聊聊原理、局限与工程取舍
  • DESK的文件搜索比Windows方便在哪几点?
  • AirPodsDesktop终极指南:在Windows上解锁苹果耳机的完整体验
  • 2026年实用降AI率软件:亲测AI率从90%降至4%的稳妥方案
  • ON DELETE CASCADE 原理与安全实践:从数据依附性到生产级联防控
  • 2026 合肥本地黄金回收 正规门店 无折旧费 全程透明 - 合扬奢侈品交易中心
  • 机器学习增强采样:从玻尔兹曼生成器到自由能计算实战
  • CefFlashBrowser:让经典Flash内容重获新生的专业解决方案
  • Windows右键菜单终极管理指南:ContextMenuManager让你的右键菜单焕然一新
  • NVIDIA Profile Inspector:解锁显卡200+隐藏设置的游戏性能优化神器
  • 破解Zotero中文文献管理难题:Jasminum插件实战指南
  • Unity2D塔防核心骨架:路径寻路、塔基绑定与波次调度
  • ContextMenuManager:免费强大的Windows右键菜单终极清理工具