三大数据库(MySQL/MongoDB/PostgreSQL)常用索引及索引失效总结
三大数据库(MySQL/MongoDB/PostgreSQL)常用索引及索引失效总结
核心前提:三者索引核心目的一致——避免全表/全集合扫描、提升查询效率,代价均为占用磁盘空间、降低写入性能;底层默认结构均以B+树为主(MongoDB WiredTiger引擎实际为B+树,官方统称B树)。
一、MySQL(InnoDB引擎,最常用,关系型)
(一)常用索引(日常99%场景够用)
-
聚簇索引(主键索引):系统默认创建,数据与索引绑定,叶子节点是完整行数据;每张表必存在(无主键自动生成隐藏rowid),主键查询无需回表,速度最快。
-
二级索引(普通索引):单字段建索引,用于单条件查询、单字段排序(如idx_age(age));叶子节点存主键值,查询需回表。
-
唯一索引:约束字段值唯一(如手机号、账号),语法:CREATE INDEX idx_phone ON user(phone) UNIQUE; 与聚簇索引逻辑一致,仅多了唯一性约束。
-
复合索引:多字段联合索引(如idx_name_age(name, age)),严格遵循「最左前缀原则」,等值查询字段放前、范围查询字段放后。
(二)索引失效场景(核心必记)
-
复合索引违反「最左前缀原则」(如索引(name,age),只查age、只查age+gender,均失效)。
-
索引字段做函数运算、四则运算(如mod(age,2)=0、age+1=20,均失效)。
-
隐式类型转换(如字段是int型,查询用字符串''18'')。
-
模糊查询:左模糊(%张三)、全模糊(%张三%)失效,仅右模糊(张三%)生效。
-
使用 !=、NOT IN、IS NOT NULL,大概率失效。
-
OR查询:两边字段无统一索引(如OR前后分别是name和age,均无索引或仅一个有索引),失效。
-
查询结果占表数据量20%-30%以上,优化器放弃索引,走全表扫描。
-
排序字段不在索引内(如查询条件用name,排序用age,且无复合索引包含name+age)。
二、MongoDB(文档型NoSQL,嵌套/数组友好)
(一)常用索引(日常99%场景够用)
-
单字段索引:单字段建索引(如db.user.createIndex({age:1})),用于单条件查询、单字段排序,与MySQL普通索引逻辑一致。
-
唯一索引:系统默认自带_id唯一索引(无法删除、不能为空、绝对唯一);可手动创建业务唯一索引(如db.user.createIndex({phone:1},{unique:true})),允许多个null值。
-
复合索引:多字段联合索引(如db.user.createIndex({name:1, age:-1})),严格遵循「最左前缀原则」,与MySQL一致。
-
多键索引:数组字段自动生成(无需手动配置),索引数组每一个元素,用于查询数组包含某单个元素(如hobby: "打球")。
(二)索引失效场景(核心必记,含Mongo特有)
1. 与MySQL一致的失效场景
- 复合索引违反最左前缀原则、索引字段做函数/运算、隐式类型转换、左模糊/全模糊查询、OR查询无统一索引、大结果集放弃索引。
2. MongoDB特有失效场景(重点)
-
使用$where运算符(如db.user.find({$where: "this.age>18"})),直接彻底不走任何索引,全集合扫描,线上严禁使用。
-
数组查询(多键索引)失效:使用$all匹配多个元素(如hobby: {$all: ["打球","听歌"]})、查询完整数组(如hobby: ["打球","听歌"])、按数组下标查询(如"hobby.0": "打球")、用$size判断数组长度(如hobby: {$size:3})。
-
自定义唯一索引查询null值(大量null值时,大概率不走索引)。
-
分片集群环境,分片键不合理,跨分片查询不走本地索引。
三、PostgreSQL(PG,全能型关系型,索引能力天花板)
(一)常用索引(日常99%场景够用,含PG特色)
-
B-tree索引:默认索引,与MySQL B+树一致,用于等值、范围查询,适配普通单字段、复合索引场景(如CREATE INDEX idx_age ON user(age))。
-
唯一索引:与MySQL一致,约束字段唯一(如CREATE UNIQUE INDEX idx_phone ON user(phone)),无Mongo的null值漏洞。
-
复合索引:遵循最左前缀原则,但优化器更智能,非严格遵循时也可能走索引(如索引(a,b,c),查询a+c也可能生效)。
-
GIN索引(PG核心特色):专为数组、JSONB、全文检索设计,解决Mongo数组查询失效问题(如CREATE INDEX idx_hobby ON user USING GIN (hobby)),支持多元素同时匹配。
-
表达式索引(PG特色):对函数/表达式建索引(如CREATE INDEX idx_lower_name ON user (lower(name))),查询需与表达式完全一致才能走索引。
(二)索引失效场景(核心必记,含PG特有)
1. 与MySQL一致的失效场景
- 复合索引违反最左前缀原则(概率低于MySQL)、索引字段做函数/运算、隐式类型转换、左模糊/全模糊查询、NOT IN/!=/IS NOT NULL大概率失效、大结果集放弃索引。
2. PostgreSQL特有失效场景(重点)
-
统计信息过时:表数据大量增删后,未执行ANALYZE 表名; 刷新统计信息,优化器误判放弃索引。
-
表达式索引不匹配:建索引时的表达式与查询表达式不一致(如索引是lower(name),查询用name='Tom')。
-
数据类型严格不匹配(比MySQL更严格):如字段是numeric型,查询用varchar型,直接失效。
-
GIN索引失效:数组/JSONB字段建普通B-tree索引(需建GIN索引)、使用=查询完整数组(需用@>操作符)。
四、三大数据库索引核心对比(速查)
| 对比维度 | MySQL | MongoDB | PostgreSQL |
|---|---|---|---|
| 常用索引 | 聚簇、二级、唯一、复合 | 单字段、唯一、复合、多键 | B-tree、唯一、复合、GIN、表达式 |
| 核心失效特色 | 严格遵循最左前缀,优化器较简单 | $where必失效,数组查询坑多 | 统计信息过时、表达式不匹配、类型严格 |
| 数组/JSON支持 | 弱(需拆表) | 强,但查询易失效 | 极强(GIN索引,无失效坑) |
| 优化器智商 | 中等 | 中等(文档场景优) | 极高(复杂场景最优) |
五、总结(极简版)
-
MySQL:够用、简单,索引失效规则固定,适合普通CRUD、高并发短连接。
-
MongoDB:嵌套/数组友好,多键索引有坑,$where严禁用,适合动态结构、快速迭代。
-
PostgreSQL:全能天花板,索引类型多、优化器强,解决前两者痛点,适合复杂查询、混合数据(JSON/数组/GIS)。
(注:文档部分内容可能由 AI 生成)
本文由萧兮的博客原创发布,欢迎转载,转载务必保留原文链接。
萧兮的博客:https://www.20010515.xyz · 原文:https://www.20010515.xyz/posts/019e4ece-bc6b-7db0-8d6f-7698d91232b4