一张5000万行的表,加索引从45秒到0.02秒——索引设计你真的会吗

简介: 本文实测5000万订单表:无索引查询45秒,加索引后仅0.02秒(提升2250倍)。详解索引原理、建索引时机、联合索引最左前缀、覆盖索引及隐式转换陷阱,干货不啰嗦!

我是小耶,干运营半路出家的野生DBA——写功课只是为了我踩过的坑,你们别再踩了!

今天不搞虚的,直接上实验:一张 5000 万行的订单表,对比无索引和有索引的查询性能。

实验环境​:MySQL 8.0,innodb_buffer_pool_size 默认配置,订单表结构含 user_idorder_dateamount 等字段。

1. 无索引查询

SELECT * FROM orders WHERE user_id = 123456;

耗时 ​45 秒​。CPU 飙升,应用超时。

2. 添加单列索引

ALTER TABLE orders ADD INDEX idx_user_id (user_id);

再次执行相同查询:​0.02 秒​。性能提升 ​2250 倍​。

原因​:InnoDB 默认使用 B+ 树索引。没有索引时,执行全表扫描,逐行读取 5000 万条数据;有索引后,通过 B+ 树进行二分查找,树高通常为 3~4 层,每次查询只需 3~4 次磁盘 I/O,所以速度极快。


什么情况下应该建索引?

  • WHERE 条件中频繁出现的列
  • JOIN 的关联列
  • ORDER BYGROUP BY 的列

什么情况下不应建索引?

  • 列的区分度极低(例如 gender 只有男/女)。索引无法有效过滤数据,反而增加维护成本。
  • 频繁更新的列(UPDATE 会同时更新索引,写性能下降)。
  • 很少作为查询条件的列(索引占空间但无收益)。

进阶1:联合索引与最左前缀原则

如果经常同时按 user_idorder_date 查询,可以建联合索引:

ALTER TABLE orders ADD INDEX idx_user_date (user_id, order_date);

联合索引的 B+ 树先按第一列排序,再按第二列排序。​查询条件必须从索引最左侧开始连续匹配​,才能使用索引。

  • WHERE user_id = 123 —— 可用
  • WHERE user_id = 123 AND order_date > '2026-01-01' —— 可用
  • WHERE order_date > '2026-01-01' —— 无法使用,因为第一列缺失
  • WHERE user_id = 123 AND amount > 100 —— 只能用到 user_id 部分,amount 在索引中不连续

如何确定联合索引的列顺序?

  • 等值查询的列放前面​,​范围查询的列放后面​。
  • 例如 WHERE user_id = 123 AND order_date > '2026-01-01',索引 (user_id, order_date) 最优。
  • 如果有多个等值条件,把区分度高的列放左边。

进阶2:覆盖索引

如果 SELECT 的列全部包含在索引中,InnoDB 可以直接从索引返回数据,​无需回表​,性能进一步提升。

CREATE INDEX idx_user_date_amount ON orders (user_id, order_date, amount);
SELECT user_id, order_date, amount FROM orders WHERE user_id = 123;

执行 EXPLAIN 会在 Extra 列显示 Using index。覆盖索引能减少大量 I/O,尤其适合统计类查询。


常见错误:隐式类型转换导致索引失效

如果索引列是字符串类型,但查询时传入数字,MySQL 会对列做隐式转换,导致索引失效。

-- phone 是 varchar,正确做法是加引号
SELECT * FROM users WHERE phone = '13800000000';  -- 走索引
SELECT * FROM users WHERE phone = 13800000000;    -- 不走索引

小结

索引是数据库性能优化的核心手段,但不是越多越好。建议:

  1. 对高频查询的 WHEREJOINORDER BY 列建索引。
  2. 联合索引遵循最左前缀原则,范围查询列放最后。
  3. 尽量使用覆盖索引避免回表。
  4. 注意隐式类型转换、函数操作对索引的影响。

你可以花 10 分钟检查下业务核心表的慢查询日志,看看哪些查询缺少合适的索引。往往一两处优化就能让整个系统性能翻倍。

小耶在手,SQL 不愁。

你们遇到过“建了索引还是慢”的情况吗?

相关文章
|
3月前
|
SQL 关系型数据库 MySQL
MySQL 高性能核心:MVCC 无锁并发机制解析
本文深入解析InnoDB的MVCC(多版本并发控制)机制:通过隐藏字段、Undo Log版本链与Read View可见性规则,实现无锁快照读,兼顾高并发与事务隔离。详解RC/RR级别差异、快照读vs当前读,并提醒Undo日志膨胀等实战坑点。
|
算法 JavaScript 大数据
高德地图 错误码说明 对照表
序号  infocode info返回值 状态描述 问题排查策略 1 10000 OK 请求正常 请求正常 2 10001 INVALID_USER_KEY key不正确或过期 开发者发起请求时,传入的key不正确或者过期  3 10002 SERVICE_NOT_AVAILABLE 没有权限使用相应的服务或者请求接口的路径拼写错误 1.开发者没有权限使用相应的服务,例如:开发者申请了WEB定位功能的key,却使用该key访问逆地理编码功能时,就会返回该错误。反之亦然。2.开发者请求接口的路径拼写错误。例如:正确的https://restapi.amap.com/v3/ip在程序中被拼装写了h
6013 0
|
6月前
|
人工智能 API 机器人
OpenClaw 用户部署和使用指南汇总
本文档为OpenClaw(原MoltBot)官方使用指南,涵盖一键部署(阿里云轻量服务器年仅68元)、钉钉/飞书/企微等多平台AI员工搭建、典型场景实践及高频问题FAQ。同步更新产品化修复进展,助力用户高效落地7×24小时主动执行AI助手。
30625 253
|
3月前
|
Rust 前端开发 JavaScript
Vite 8 背后的秘密:为什么尤雨溪选择了 Oxc
Oxc(The Oxidation Compiler)是用Rust打造的高性能JS/TS工具链,含解析、Lint、格式化、转换、压缩等核心组件。内存零GC、零拷贝解析、共享AST架构,使Oxlint比ESLint快100倍、Oxfmt比Prettier快30倍。已集成Vite 8,5分钟即可升级开发体验!
755 1
Vite 8 背后的秘密:为什么尤雨溪选择了 Oxc
|
3月前
|
SQL 数据库管理 索引
别再滥用IN子查询了!用JOIN改写,从8秒到0.4秒(附优化步骤)
本文揭秘SQL子查询性能陷阱:IN慢因临时表+全量扫描;推荐JOIN改写——利用索引、避免磁盘IO。实测500万订单下,JOIN比IN快20倍!附三步改写法与NULL避坑指南。
|
1月前
|
人工智能 监控 测试技术
银行业AI架构:从裸调API到六层技能体系
# 银行AI智能体架构实战:从单体到Skill协同的技术演进 ## 痛点:银行IT架构的三重困境 走在任何一家银行的科技部走廊里,你都能听到同样的叹息:系统又慢了、需求又排不上、监管又来查了。这不是某一家银行的困境,而是整个银行业IT架构的共性问题。我们把它拆解为三重困境。 **困境一:单体系
|
2月前
|
存储 人工智能 自然语言处理
知识库为谁而建 ?
随着 Agent 的逐步广泛应用,知识库的使用者正在从人变成 Agent。 知识库的设计逻辑、维护方式、甚至存在的意义,都需要重新思考。
814 10
知识库为谁而建 ?
|
2月前
|
Java Windows
JDK 8 安装与环境变量配置教程(jdk-8u121-windows-x64.exe 详细步骤)
本教程详解JDK 8u121 Windows 64位安装与配置:含管理员运行、路径选择、JAVA_HOME及Path环境变量设置,并通过java/javac -version命令快速验证,步骤清晰,适配Win10/Win11。
|
3月前
|
监控 数据挖掘 测试技术
GPT-5.5 技术观察:企业落地大模型,要先解决“调用层”问题
GPT-5.5 的出现,会让企业 agent 的上限更高。但决定项目能不能上线的,往往不是模型上限,而是调用层、权限、成本和稳定性。
313 0
|
4月前
|
存储 人工智能 开发者
AI Agent 越来越难迭代,你缺少的不是功能
还在担心 Token 消耗过多?还在纠结 Agent 难以优化?不改一行业务代码,LoongSuite Python 探针帮你把一次请求从头到尾捋顺:哪一步访问了什么模型、调用了什么工具、召回了哪些文档、花费了多少 token、上下文发生了什么变化。
362 58

热门文章

最新文章