外观
SQL、索引与执行计划
- 状态:未准备
- 适用方向:共用 / Go 后端重点
- 最近复习:待填写
- 下次复习:待安排
一句话回答
索引以额外空间和写入成本换取特定访问路径的效率;优化从真实 SQL、数据分布和执行计划出发,而不是见到 WHERE 就加索引。
原理解释
以 MySQL 8.x InnoDB 为例,常见索引使用 B+ 树;聚簇索引叶子保存行数据,二级索引叶子携带主键。二级索引找到主键后可能需要回表;覆盖索引能从索引取得本次查询所需列,但也增加维护成本。
联合索引 (conversation_id, created_at, id) 按元组顺序排列,适合按会话筛选再按时间与 ID 排序。最左前缀描述有效访问方式,不等于遗漏首列永远不能使用索引;优化器可能选全索引扫描等路径,应看实际计划。
sql
SELECT id, created_at
FROM messages
WHERE conversation_id = ?
AND (created_at < ? OR (created_at = ? AND id < ?))
ORDER BY created_at DESC, id DESC
LIMIT 20;以上为假设表结构的游标分页例子,参数由驱动绑定。稳定唯一的排序组合避免同时间记录跳漏;是否有效利用联合索引仍需用实际数据验证。深 OFFSET 常需扫描并丢弃许多行,游标分页则不适合任意跳页。
场景与边界
函数包裹列、隐式转换、前导通配符等可能妨碍有效范围查找,但不能一概说“索引完全失效”。EXPLAIN 看访问方式、选中索引、估计行数和额外排序;支持的版本可用 EXPLAIN ANALYZE 对照实际执行,注意它会执行查询。小表或低选择性条件可能全表扫描更划算。
项目中的应用
沿 EinoTalk MySQL 访问核对消息历史查询、表结构和索引;上述列名只是教学假设,不代表项目现有 schema。
常见追问
- 索引越多越好? 占空间并增加插入、更新、删除成本。
- 唯一索引只加速吗? 还提供数据库层并发唯一性约束,适合业务去重。
- SELECT * 为什么要谨慎? 增加传输和解码成本,也可能失去覆盖访问机会。