PHP 数据库索引优化面试题解析

2次阅读

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

PHP 数据库索引优化面试题解析

数据库索引优化是 PHP 后端开发面试中的高频考点,核心不在于死记命令,而在于理解“为什么加索引”“加在哪”“加了反而变慢怎么办”。下面从实际场景出发,拆解几个典型问题。

哪些字段适合建索引?

适合建索引的字段需同时满足:查询频率高、区分度高(如 user_id、email)、常出现在 WHERE、ORDER BY、JOIN 条件中。比如用户登录时查 emailstatus,组合索引 (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(如 laravelDB::listen()),对 >100ms 的查询自动触发 EXPLAIN

注意:即使写了 WHERE status = 1,如果 status 没索引或类型不匹配(如字段是 TINYINT,却传字符串 ‘1’),也会全表扫描。

复合索引顺序怎么定?

顺序决定索引能否被复用。口诀:等值查询放前面,范围查询放最后,排序字段可跟在后面。

例如查询: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+ 树原理。

text=ZqhQzanResources