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

能否通过索引提升PostgreSQL LEFT OUTER JOIN查询性能?

优化PostgreSQL多表关联查询性能(无需修改SQL)

我运营一个图片托管网站,数据库包含image、user表,以及记录多对多关系的collaborators表(一张图片可关联多个协作用户)。当前使用PostgreSQL执行以下查询,用于找出用户999是所有者或协作者的所有图片:

SELECT image.id
FROM image
LEFT OUTER JOIN collaborators ON (image.id = collaborators.image_id)
WHERE (image.user_id = 999 OR collaborators.user_id = 999)

数据库约有10万用户、60万图片,collaborators表条目极少,但查询耗时超4秒。执行计划如下:

Hash Right Join  (cost=107937.02..110540.78 rows=3318 width=4) (actual time=2928.556..4428.901 rows=25 loops=1)
  Hash Cond: (collaborators.image_id = image.id)
  Filter: ((image.user_id = 999) OR (collaborators.user_id = 999))
  Rows Removed by Filter: 653094
  ->  Seq Scan on collaborators  (cost=0.00..30.40 rows=2040 width=8) (actual time=0.013..0.016 rows=8 loops=1)
  ->  Hash  (cost=97220.01..97220.01 rows=653201 width=8) (actual time=2905.239..2905.240 rows=653119 loops=1)
        Buckets: 131072  Batches: 16  Memory Usage: 2623kB
        ->  Seq Scan on image  (cost=0.00..97220.01 rows=653201 width=8) (actual time=0.016..1689.448 rows=653119 loops=1)
Planning time: 0.228 ms
Execution time: 4429.183 ms

由于SQL由Django生成无法修改,可通过以下索引优化查询性能:

索引优化方案

1. 为image表创建覆盖索引

当前查询需要筛选image.user_id = 999的记录,同时要获取image.id用于关联。创建覆盖索引可以让数据库直接从索引取数,避免全表扫描:

CREATE INDEX idx_image_user_id_id ON image (user_id) INCLUDE (id);

这个索引能快速定位用户999的所有图片,且直接返回id字段,无需回表查询额外数据。

2. 为collaborators表创建复合索引

查询需要通过collaborators.user_id = 999找到关联图片ID,再和image表关联。创建复合索引:

CREATE INDEX idx_collaborators_user_id_image_id ON collaborators (user_id, image_id);

该索引能快速定位用户999作为协作者的所有image_id,且因为包含image_id,可直接用于关联查询,避免扫描整个collaborators表。

3. 验证优化效果

创建索引后重新执行查询,查看执行计划:

  • 应不再出现image表的全表扫描(Seq Scan),替换为索引扫描(Index Scan)
  • collaborators表的扫描也会变成索引扫描,返回行数大幅减少

优化原理

当前执行计划中,数据库对65万行的image表做全表扫描,再通过哈希连接和过滤筛选出仅25条有效数据,大部分时间浪费在无效数据的扫描和过滤上。通过上述索引:

  • idx_image_user_id_id直接定位用户999的所有图片,跳过全表扫描
  • idx_collaborators_user_id_image_id快速找到用户999作为协作者的图片ID,再关联image表
  • 两个索引配合后,数据库能高效合并所有者和协作者的图片集合,大幅缩短查询时间

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 18:16:04