在关系型数据库(MySQL、PostgreSQL、Oracle 等)中,优化器(Optimizer)选择索引的过程,本质上是一个基于代价(Cost-Based)的决策过程。下面从“整体流程 → 判断依据 → 常见影响因素 → 实战建议”四个层面说明。
一般数据库优化器选择索引会经历以下步骤:
解析 SQL
生成候选执行计划
估算每种计划的代价(Cost)
选择代价最小的计划
索引必须满足:
❌ 错误示例(索引失效):
WHERE DATE(create_time) = '2024-01-01'
WHERE phone = 13800000000 -- phone 是字符串
✅ 正确示例:
WHERE create_time >= '2024-01-01'
AND create_time < '2024-01-02'
选择性越高,越容易走索引
优化器会估算:
选择性 = 满足条件的行数 / 总行数
-- 覆盖索引
INDEX(user_id, status)
SELECT status FROM user WHERE user_id = 1;
优化器会判断:
如果估算扫描行数超过一定比例(如 20%~30%),可能放弃索引。
优化器依赖:
统计信息不准 → 选错索引
-- MySQL
ANALYZE TABLE user;
-- PostgreSQL
ANALYZE user;
常见原因:
| 原因 | 说明 |
|---|---|
| 隐式转换 | 类型不一致 |
| 函数操作 | UPPER(name) |
| 前导模糊 | LIKE '%abc' |
| 选择性太低 | 性别、状态 |
| 回表代价高 | 非覆盖索引 |
| 统计信息旧 | 优化器误判 |
| 索引顺序不对 | 不满足最左前缀 |
-- MySQL
SELECT * FROM user FORCE INDEX(idx_user_status)
WHERE user_id = 1;
-- Oracle
SELECT /*+ INDEX(t idx_name) */ * FROM t;
⚠️ Hint 是“最后手段”,不是首选
优化器不是“看有没有索引”,而是“算用索引划不划算”
索引是否被选中 = 选择性 + 回表成本 + 统计信息 + SQL 写法
如果你愿意,可以贴一条 具体 SQL + 表结构 + 执行计划,我可以帮你分析为什么没走索引。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。