当表中time、name列已有单独索引时,创建联合索引是否有意义?
答案:会产生明显差异,具体取决于你的查询场景
当然会有差异!这得结合你实际执行的查询类型来分析,下面分几种核心场景说明:
1. 针对同时过滤name和time的查询,复合索引效率更高
比如你执行这类查询:
SELECT other_column FROM my_table WHERE name = 'Bob' AND time BETWEEN 1600000000 AND 1700000000;
此时index_name_and_time(name,time的复合索引)能直接发挥最优作用:它是先按name排序,再在相同name的范围内按time排序,数据库可以快速定位到name='Bob'的所有行,再在这个子集里筛选符合time条件的数据,全程不需要回表或者做索引合并操作。
而如果只用原来的两个单独索引,数据库要么只能用index_name找到所有name='Bob'的行,再回表校验time;要么尝试做索引合并(同时用两个索引再合并结果),这两种方式的性能都远不如直接使用复合索引。
2. 针对按name分组/过滤后按time排序的查询,复合索引能避免额外排序
比如这类查询:
SELECT name, MIN(time) FROM my_table GROUP BY name; -- 或者 SELECT * FROM my_table WHERE name LIKE 'A%' ORDER BY time DESC;
复合索引(name,time)的有序性可以直接被利用:分组时能快速获取每个name对应的time极值,排序时也不需要额外对time做排序操作。而用单独的索引的话,数据库需要先通过index_name拿到符合条件的name,再回表取出time字段做排序/聚合,性能差距会很明显。
3. 仅单独过滤name或time的场景,差异不大
- 如果你的查询只过滤
name(比如SELECT * FROM my_table WHERE name = 'Alice';),复合索引(name,time)和原来的index_name效果几乎一致,因为复合索引的前导列是name,数据库可以直接用它来定位数据。 - 如果你的查询只过滤
time(比如SELECT * FROM my_table WHERE time > 1650000000;),复合索引完全派不上用场,还是得依赖原来的index_time。
额外注意:索引维护的开销
创建这个复合索引会增加数据库的存储占用,同时在执行插入、更新、删除操作时,需要多维护一个索引,会带来一定的写入性能损耗。所以要不要创建它,得看你是否真的有大量上述第一、第二种场景的查询——如果这类查询占比很高,那创建这个复合索引带来的查询性能提升完全值得;如果几乎没有这类查询,那反而会白白增加开销。
内容的提问来源于stack exchange,提问作者juung666
相关产品推荐
相关产品推荐

