有没有想过:为什么索引能加快查询速度?深入 B+ 树原理,小白也能秒懂!

视频看了几百小时还迷糊?关注我,几分钟让你秒懂!


很多开发者会用索引,但一问“为什么索引快?”就支支吾吾。今天我们就抛开黑盒,用Java + Spring Boot的视角,结合生活化类比和底层原理,彻底搞懂这个问题。


一、没有索引时:全表扫描 = 翻整本字典

假设你有一张用户表user_info,100 万条数据:

CREATE TABLE user_info ( id BIGINT PRIMARY KEY, phone VARCHAR(20), name VARCHAR(50) );

现在你要查手机号为138****1234的用户:

SELECT * FROM user_info WHERE phone = '138****1234';

❌ 没有索引的情况

数据库只能一行一行地从磁盘读取数据,直到找到匹配项 —— 这叫全表扫描(Full Table Scan)

  • 最坏情况:查到最后一条才找到 → 扫描 100 万行
  • 平均情况:也要扫 50 万行
  • 每次磁盘 I/O 都很慢(机械硬盘约 10ms/次)

💥 100 万次 I/O?那不得卡死!


二、有了索引后:像查字典目录一样快

我们给phone加个普通索引:

ALTER TABLE user_info ADD INDEX idx_phone (phone);

这时 MySQL(InnoDB 引擎)会为phone列构建一棵B+ 树

✅ B+ 树长什么样?(简化版)

想象一棵三层的树:

[130... | 150... | 180...] / | \ [1300000...1309999] [1500000...1509999] [1800000...1809999] | | | 实际数据指针 实际数据指针 实际数据指针
  • 非叶子节点:只存索引值(如手机号区间),用于快速导航
  • 叶子节点:存完整的索引值 + 主键(或行指针),并且双向链表连接

🔍 查询过程(以138****1234为例):

  1. 从根节点开始:138...属于130... ~ 150...区间 → 走中间分支
  2. 到第二层:定位到1380000 ~ 1389999的页
  3. 在叶子节点中二分查找,快速定位到138****1234
  4. 通过主键(或聚簇索引)回表拿到完整行数据(如果是覆盖索引则不用回表)

✅ 整个过程只需3 次磁盘 I/O(树高为 3),而不是 50 万次!

📌 关键点:B+ 树高度低、扇出大(一个节点可存上千个指针),所以查询效率极高


三、用 Java 模拟 B+ 树查找 vs 线性查找

虽然真实 B+ 树复杂,但我们用简化代码感受差距:

import java.util.*; public class IndexSimulation { // 模拟 100 万用户数据(无序) static List<User> users = new ArrayList<>(); // 模拟 phone -> id 的 B+ 树索引(用 TreeMap 近似) static TreeMap<String, Long> phoneIndex = new TreeMap<>(); static { // 初始化数据 for (long i = 1; i <= 1_000_000L; i++) { String phone = "138" + String.format("%07d", i); users.add(new User(i, phone, "User" + i)); phoneIndex.put(phone, i); // 构建索引 } } // 无索引:线性查找 public static User findByPhoneWithoutIndex(String targetPhone) { for (User user : users) { if (user.getPhone().equals(targetPhone)) { return user; } } return null; } // 有索引:TreeMap(红黑树,近似 B+ 树的有序查找) public static User findByPhoneWithIndex(String targetPhone) { Long id = phoneIndex.get(targetPhone); if (id != null) { // 实际数据库会通过主键回表,这里简化 return users.get((int)(id - 1)); } return null; } public static void main(String[] args) { String target = "138500000"; long start1 = System.currentTimeMillis(); User u1 = findByPhoneWithoutIndex(target); long time1 = System.currentTimeMillis() - start1; long start2 = System.currentTimeMillis(); User u2 = findByPhoneWithIndex(target); long time2 = System.currentTimeMillis() - start2; System.out.println("无索引耗时: " + time1 + " ms"); System.out.println("有索引耗时: " + time2 + " ms"); // 输出示例: // 无索引耗时: 15 ms // 有索引耗时: 0 ms } static class User { private Long id; private String phone; private String name; // 构造方法、getter 省略 public User(Long id, String phone, String name) { this.id = id; this.phone = phone; this.name = name; } public String getPhone() { return phone; } } }

💡 虽然TreeMap是红黑树,不是 B+ 树,但它体现了有序结构 + 快速查找的核心思想。

在真实数据库中,B+ 树更适合磁盘存储(节点大小 = 16KB,一次 I/O 读一页),而红黑树适合内存。


四、Spring Boot 中如何验证索引生效?

1. 开启 SQL 日志(application.yml)

logging: level: com.yourpackage.mapper: debug

2. 使用EXPLAIN分析

// 在 Mapper 中加一个 explain 方法(仅开发环境用) @Select("EXPLAIN SELECT * FROM user_info WHERE phone = #{phone}") List<Map<String, Object>> explainFindByPhone(@Param("phone") String phone);

调用后你会看到:

字段说明
typeref表示使用了索引
keyidx_phone表示命中了哪个索引
rows扫描行数(理想是 1)

如果type=ALL,说明没走索引!


五、常见误区:以为加了索引就一定快?

❌ 反例 1:对索引列使用函数

-- 索引失效! SELECT * FROM user_info WHERE UPPER(phone) = '138****1234';

❌ 反例 2:模糊查询左通配

-- 索引失效! SELECT * FROM user_info WHERE phone LIKE '%1234';

✅ 正确写法:

-- 右通配可以走索引 SELECT * FROM user_info WHERE phone LIKE '138%';

❌ 反例 3:联合索引不遵循最左前缀

-- 有索引 (name, phone),但只查 phone → 不走索引 SELECT * FROM user_info WHERE phone = '138****1234';

六、为什么 B+ 树比哈希、二叉树更适合数据库?

数据结构是否适合数据库索引原因
哈希表只支持等值查询,不支持范围(如WHERE create_time > ?
二叉搜索树树太高(100 万数据 → 高度约 20),I/O 太多
B 树⚠️非叶子节点存数据,导致一页存的指针少,树更高
B+ 树所有数据在叶子节点 + 叶子链表 + 非叶子只存索引 → 树更矮、范围查询快

InnoDB 选择 B+ 树,就是因为它兼顾等值、范围、排序查询,且磁盘友好


七、总结:索引快的本质

对比项无索引有索引(B+ 树)
查找方式线性扫描树形分治
时间复杂度O(N)O(log N)
磁盘 I/O 次数几十万次通常 2~4 次
范围查询快(叶子节点链表)
内存占用无额外需要存储索引结构

一句话总结

索引通过预排序 + 树形结构,把“大海捞针”变成“按图索骥”,从而实现毫秒级查询。


视频看了几百小时还迷糊?关注我,几分钟让你秒懂!

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

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

相关文章

11种AI论文创作助手,提供LaTeX排版与语义优化双重支持

工具对比排名 工具名称 核心优势 支持LaTeX 适用场景 aibiye AIGC率降个位数&#xff0c;兼容知网规则 是 AI痕迹强处理 aicheck 学术改写优化&#xff0c;语义保留佳 是 格式统一化 askpaper 降重降AI一体&#xff0c;20分钟快速响应 是 初稿优化 秒篇 人类特…

重磅!谷歌推出全新TranslateGemma翻译模型系列

1 月 16 日&#xff0c;Google 正式推出了全新开放翻译模型系列 TranslateGemma。该系列基于 Gemma 3 架构开发&#xff0c;提供 4B、12B 和 27B 三种参数规模。Google 表示&#xff0c;TranslateGemma 的推出标志着开放翻译技术的又一重大进展&#xff0c;旨在打破语言障碍&am…

歌乐枕西,嘉陵抱东,磁器口藏千年韵

磁器口古镇坐落于重庆市沙坪坝区东北部&#xff0c;是一座拥有千年历史的巴渝文化地标。它依山而建&#xff0c;东临嘉陵江&#xff0c;西靠歌乐山&#xff0c;由三山环抱&#xff0c;两溪萦绕&#xff0c;构成了独特的山水格局。古镇始建于北宋年间&#xff0c;明清以来因瓷器…

11种AI论文创作工具,集成LaTeX排版与自动化内容优化技术

工具对比排名 工具名称 核心优势 支持LaTeX 适用场景 aibiye AIGC率降个位数&#xff0c;兼容知网规则 是 AI痕迹强处理 aicheck 学术改写优化&#xff0c;语义保留佳 是 格式统一化 askpaper 降重降AI一体&#xff0c;20分钟快速响应 是 初稿优化 秒篇 人类特…

光圈智选首页升级:升佣 + 选品提速双 buff

光圈智选新版首页已完成重构上线&#xff0c;围绕带货场景中的“高效选品”与“收益提升”两大核心痛点优化&#xff0c;打通从选品到收益转化的全链路体验&#xff0c;为达人、商家的带货运营提供更高效的工具支撑。选品能力升级&#xff1a;精准匹配需求&#xff0c;提升选品…

导师推荐!MBA开题报告TOP8 AI论文写作软件测评

导师推荐&#xff01;MBA开题报告TOP8 AI论文写作软件测评 2026年MBA开题报告写作工具测评&#xff1a;精准选择&#xff0c;提升效率 随着AI技术的不断进步&#xff0c;越来越多的MBA学生开始借助智能写作工具来提高论文写作效率。然而&#xff0c;面对市场上琳琅满目的AI论文…

基于stm32的四旋翼无人机的设计——飞行控制系统软件设计

2 四旋翼无人机设计总体思路 确定无人机基本需求&#xff0c;主要包括无人机的功能、性能、成本、功耗、尺寸和重量等。确定这些之后&#xff0c;就可以针对这些需求进行硬件模块的选择以及软件的初步构思。 对无人机进行系统设计&#xff0c;把实际问题转变为工程问题&#xf…

惊魂一刻!重装系统误删分区,数据救援大揭秘

在数字化时代&#xff0c;数据已成为我们生活和工作中不可或缺的一部分。然而&#xff0c;在操作电脑的过程中&#xff0c;有时会因为疏忽或误操作而导致数据丢失&#xff0c;其中&#xff0c;重装系统时误将所有分区删除便是一种常见且令人头疼的情况。这种误操作往往会导致存…

AIDL Hal 开发笔记3---- stable-c HAL 实例分析

目录stable-c HAL 实例分析在 HIDL HAL 中 聊过 Same-Process HALs&#xff0c;这类 hal 的调用对性能要求高&#xff0c;一般直接链接&#xff0c;不适用跨进程的方式来调用。 在 AIDL HAL 中&#xff0c;与之对应的是 stable-c HAL。stable-c HAL 就是一个对外接口稳定的 so …

AIDL Hal 开发笔记4----驱动开发

目录一、编写Linux 内核驱动1.1 编写驱动1.2 将模块编译进内核二、Native 程序测试驱动程序三、权限配置驱动开发 一、编写Linux 内核驱动 1.1 编写驱动 Linux 驱动实际就是一个 Linux 内核模块。 首先&#xff0c;我们需要理解什么是内核模块&#xff1f;简单来说&#x…

基于PLC的卷扬机控制系统

三、卷扬机控制系统 &#xff08;一&#xff09;卷扬机的基本结构 如图3-1所示&#xff0c;卷扬机是由一个电机通过卷筒来带动左右两个小车上下行的工业机器。在工作过程中&#xff0c;使用一个电机同时拖动两个小车&#xff0c;使左右两个小车交替运行&#xff0c;当左车&…

基于51单片机的出租车计价器

3出租车计价器硬件设计 硬件是一个电子器具能否顺利运行的重要保障&#xff0c;它是软件的物质基础和载体。本系统的硬件设计主要包含K24C02记忆存储模块&#xff0c;用于存储数据&#xff1b;DS1302时钟模块&#xff0c;为计价器计时&#xff1b;A44E霍尔传感器电路&#xff0…

收藏级指南:Agentic RAG 彻底升级传统RAG,打造能干活的AI数字同事

Agentic RAG作为传统RAG的颠覆性升级方案&#xff0c;核心是将静态的“检索-生成”流程&#xff0c;重构为智能体驱动的动态自适应工作流。传统RAG仅能完成单次问答的闭环&#xff0c;而Agentic RAG凭借推理规划、工具调用、自我修正的核心能力&#xff0c;可承接复杂任务落地。…

QML基本元素

元素可以被分为可视化元素与非可视化元素。一个可视化元素&#xff08;例如矩形框Rectangle&#xff09;有着几何形状并且可以在屏幕上显示。一个非可视化元素&#xff08;例如计时器Timer&#xff09;提供了常用的功能&#xff0c;通常用于操作可视化元素。现在我们将专注于几…

交直流可编程电源(技术资料) 直流电源是直流输出0-30V 5A TL494 线路; 交流电压...

交直流可编程电源(技术资料&#xff09; 直流电源是直流输出0-30V 5A TL494 线路&#xff1b; 交流电压是10-120HZ可变频&#xff0c;0-30V幅度可调&#xff0c;5A输出&#xff1b; 变频交流电源部分是MEGA8DDS芯片D类数字功放做的。 电路原理: 经典的TL494开关电源线路 开关电…

DevSecOps时代测试工具的进化论:从功能验证到全链路质量保障

DevSecOps时代测试工具的进化论&#xff1a;从功能验证到全链路质量保障 在数字化转型加速的今天&#xff0c;软件开发周期持续缩短&#xff0c;安全威胁日益复杂&#xff0c;传统的"开发-测试-部署"线性流程已难以应对当下挑战。随着DevSecOps理念的深入实践&#x…

收藏级!大厂后端面试全流程复盘+大模型从入门到实战学习礼包

对于计算机专业应届毕业生而言&#xff0c;每年初秋的互联网大厂校招季&#xff0c;既是机遇与挑战交织的关键窗口期&#xff0c;更是检验四年专业积淀与技术能力的“终极实战场”。作为去年成功斩获字节跳动、阿里巴巴等多家头部大厂后端开发Offer的亲历者&#xff0c;同时也是…

【Java毕设全套源码+文档】基于springboot的公务员考试管理系统设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

基于Arduino的物流分拣控制系统设计

摘 要 为了提高当前物流分拣系统的工作效率和分拣正确率&#xff0c;满足市场对该行业的智能化需求&#xff0c;改善快递行业的经济性&#xff0c;本项目利用机械臂作为分拣工具&#xff0c;抓取物品并送到指定位置&#xff1b;利用光电对管作为扫描识别仪器&#xff0c;检测…

本土DevOps领军者Gitee:如何重塑中国企业研发效能新范式

本土DevOps领军者Gitee&#xff1a;如何重塑中国企业研发效能新范式 在数字化转型进入深水区的当下&#xff0c;研发效能已成为决定企业竞争力的关键变量。根据IDC最新报告&#xff0c;到2025年&#xff0c;采用成熟DevOps实践的企业将比同行实现50%以上的交付速度优势。这一背…