数据库索引优化核心在于理解“为何加、加在哪、为何变慢”:高查询频次且高区分度字段(如email、user_id)适合建索引,避免低区分度、频繁更新或text/blob字段;通过慢日志、explain及php监控定位未走索引的慢查;复合索引需遵循等值→范围→排序顺序;索引过多会降低写性能、增加磁盘占用并导致优化器误选,需依业务读写特征权衡。

数据库索引优化是 PHP 后端开发面试中的高频考点,核心不在于死记命令,而在于理解“为什么加索引”“加在哪”“加了反而变慢怎么办”。下面从实际场景出发,拆解几个典型问题。
哪些字段适合建索引?
适合建索引的字段需同时满足:查询频率高、区分度高(如 user_id、email)、常出现在 WHERE、ORDER BY、JOIN 条件中。比如用户登录时查 email 和 status,组合索引 (email, status) 比单列索引更高效——MySQL 能用最左前缀原则命中。
避免对以下字段建索引:
- 低区分度字段(如 gender、is_deleted),索引选择性差,优化效果微弱
- 频繁更新的字段(如 view_count),每次更新都触发 B+ 树调整,写入开销大
- TEXT/BLOB 类型字段,除非加前缀索引(如
INDEX(title(50)))
如何发现没走索引的慢查询?
在 PHP 应用中,不能只看页面响应时间,要下沉到 SQL 层。常用方法:
立即学习“PHP免费学习笔记(深入)”;
- 开启 MySQL 慢查询日志:
slow_query_log = ON,配合long_query_time = 1 - 用
EXPLAIN分析执行计划:重点看 type(尽量为 ref/const)、key(是否用了索引)、rows(扫描行数是否远小于表总行数) - PHP 中记录耗时并打印 SQL(如 Laravel 的
DB::listen()),对 >100ms 的查询自动触发 EXPLAIN
注意:即使写了 WHERE status = 1,如果 status 没索引或类型不匹配(如字段是 TINYINT,却传字符串 '1'),也会全表扫描。
IEStore是一款B2C独立网上商店系统,适合企业及个人快速构建个性化网上商店。系统是基于PHP语言及MYSQL数据库构架开发的跨平台开源程序。IEStore网上商店系统不仅在产品功能、稳定性、安全性和SEO支持(搜索引擎优化)等方面具有在同类产品领先地位,重要的是在功能架构上、操作上符合国际化标准,成为国际化电子商务的最佳软件选择之一。功能概要国际化标准IEStore网上商店系统是一个带有多国
复合索引顺序怎么定?
顺序决定索引能否被复用。口诀:等值查询放前面,范围查询放最后,排序字段可跟在后面。
例如查询:SELECT * FROM orders WHERE uid = 123 AND created_at > '2024-01-01' ORDER BY amount DESC
- 推荐索引:
INDEX(uid, created_at, amount) - 错误写法:
INDEX(created_at, uid)—— 因为created_at是范围查询,后续字段无法使用最左前缀 - 若还有
WHERE uid = ? AND status = ?,且 status 区分度高,可扩展为INDEX(uid, status, created_at)
索引不是越多越好,为什么?
每多一个索引,都会带来三重代价:
- 写性能下降:INSERT/UPDATE/DELETE 时,MySQL 要同步更新所有相关索引的 B+ 树
- 磁盘空间占用:索引本身需要存储,尤其大文本前缀索引或联合索引字段多时明显
-
优化器选错索引:当多个索引都可能命中时,MySQL 统计信息不准可能导致选错执行计划(可用
FORCE INDEX临时干预,但属下策)
上线前建议用 pt-duplicate-key-checker 工具检查冗余索引,例如已有 (a,b),再建 (a) 就是冗余。
索引优化本质是权衡:读多写少的报表类表可适当多建;高频交易类表则优先保写入吞吐。真正考察的是你能否结合业务场景做判断,而不是背出 B+ 树原理。










