多列唯一索引vs单列索引:业务场景选型与索引顺序疑问
咱们一步步拆解你的三个问题:
1. 现有联合唯一索引能否满足查询需求?
你创建的(product_id, item_id)联合唯一索引可以被你的查询语句利用,但有个细节需要注意:它能帮你快速定位product_id = 'some-id'的所有行,但因为查询条件里还有item_type=2,数据库需要在找到这些行后,额外过滤item_type的条件。
不过好在你的查询只返回item_id,而这个字段已经包含在联合索引里了,所以这是一个覆盖索引——数据库不需要回表去查原数据,直接从索引里就能拿到结果,这能节省不少性能开销。
如果后续item_type的查询频率很高,你可以考虑把item_type加入联合索引(比如(product_id, item_type, item_id)),进一步减少过滤成本,但就当前需求来说,现有的联合唯一索引已经能满足基本查询要求了。
2. 是否需要额外添加product_id单列索引?
完全不需要。因为(product_id, item_id)联合索引的最左列就是product_id,对于product_id = 'some-id'的查询,这个联合索引的效果甚至比单列product_id索引更好:
- 单列索引只能帮你定位到对应的行,之后还需要回表去取
item_id; - 而你的联合索引本身就包含
item_id,属于覆盖索引,直接就能返回结果,性能更优。
额外加单列索引只会浪费存储空间,还会增加数据插入/更新时的索引维护成本,完全没必要。
3. 创建唯一索引时,列的顺序会产生影响吗?
当然会,而且影响很大,主要体现在两个方面:
唯一约束的逻辑
(product_id, item_id)和(item_id, product_id)的唯一约束效果是等价的——都是保证两列的组合值唯一,不会出现重复的product_id+item_id对。
查询性能的影响
这是核心差异:
- 如果你的查询是以
product_id为条件(就像你现在的语句),(product_id, item_id)的索引能直接利用最左前缀匹配,快速定位数据; - 但如果索引顺序是
(item_id, product_id),你的查询语句就无法利用这个索引了——因为查询条件里没有item_id的等值条件,数据库只能做全索引扫描或者全表扫描,性能会大幅下降。
另外,从索引效率角度,通常建议把基数更高的列放在前面(这里product_id有100K个值,基数比item_id的50K更高),这样能更快缩小查询范围,提升索引的过滤效率。
内容的提问来源于stack exchange,提问作者user144546

