You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Like表复合索引优化:查询性能异常与最优索引方案问询

问题分析与优化建议

先拆解下你的查询慢的核心原因,再给出针对性的优化方案:

异常点分析

从你提供的查询计划和现有索引来看,主要有这几个问题导致查询耗时过高:

  1. 索引选择不匹配:你的查询WHERE条件是object_id = %s AND content_type_id = %s AND "like" = %s,但数据库却选择了单字段的like_417f1b1d(仅content_type_id的索引)。这意味着数据库先扫描所有匹配content_type_id的行(多达127万行),再在这些行里过滤object_id和like字段,这种大范围扫描+事后过滤的方式自然效率极低。
  2. 现有唯一索引无法被利用:你创建的like_user_id_uniq索引是(user_id, content_type_id, object_id),但你的查询里并没有指定user_id作为过滤条件。由于索引的前缀匹配原则,数据库无法利用这个索引的后续字段来快速定位数据,相当于这个索引对当前查询完全无效。
  3. 统计信息可能过时:查询计划里估计返回1行,但索引扫描却返回了127万行,说明数据库的统计信息可能不准确,导致它选错了索引策略。

最优索引方案

针对你的查询场景(检查用户是否点赞某对象、查询点赞用户列表),需要创建匹配WHERE条件的组合索引,推荐两种方案:

方案1:覆盖过滤条件的组合索引

CREATE INDEX idx_like_content_object_like ON "like" USING btree (content_type_id, object_id, "like");
  • 索引顺序逻辑:先放等值匹配的content_type_id和object_id(这两个是精确匹配,基数更高),最后放like布尔字段(用于过滤)。
  • 优势:数据库可以直接通过这个索引定位到所有符合content_type_id + object_id + like条件的行,无需再回表扫描大量数据,直接拿到需要的user_id去关联accounts_user表,大幅降低查询成本。

方案2:包含式组合索引(更轻量化)

如果like字段的基数很低(比如大部分记录都是true或false),可以把它作为包含列,减少索引大小:

CREATE INDEX idx_like_content_object ON "like" USING btree (content_type_id, object_id) INCLUDE ("like");
  • 优势:索引只存储content_type_id和object_id的键值,like作为附加列不参与索引排序,索引体积更小,维护成本更低,同样能满足过滤需求。

额外建议

  1. 更新统计信息:如果创建新索引后仍然有问题,先更新表的统计信息,让数据库能准确评估索引成本:
ANALYZE "like";
  1. 避免使用SQL关键字作为表名:like是SQL的关键字,虽然你用引号括起来没问题,但长期来看容易引发语法错误,建议重命名表(比如改成user_like)。

内容的提问来源于stack exchange,提问作者EralpB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:26:53