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

PostgreSQL并行执行计划解读与向量查询性能不达预期排查

问题背景

我有一张存储100万条384维向量的表,其中vector列类型为char[]。尝试通过并行化加速使用pgvector扩展<#>点积算子的查询,测试SQL如下:

EXPLAIN ANALYZE
WITH Vars(key) as (
    VALUES (array_fill(1, ARRAY[384])::vector)
)
SELECT content_id
FROM MyTable, Vars
ORDER BY vector::int[]::vector <#> key
LIMIT 10;

key是全1的测试向量,vector为pgvector定义的类型(类似real[])。在AWS RDS免费版2vCPU实例上运行该查询,预期并行化后性能接近翻倍,但实际提升有限。

无并发设置及执行计划输出

设置语句:

set max_parallel_workers = 1;
set max_parallel_workers_per_gather = 1;
set enable_parallel_hash = off;

执行计划:

Limit  (cost=94267.29..94268.44 rows=10 width=12) (actual time=15624.961..15634.530 rows=10 loops=1)
   ->  Gather Merge  (cost=94267.29..161913.85 rows=588231 width=12) (actual time=15624.958..15634.524 rows=10 loops=1)
         Workers Planned: 1
         Workers Launched: 1
         ->  Sort  (cost=93267.28..94737.86 rows=588231 width=12) (actual time=15607.302..15607.305 rows=7 loops=2)
               Sort Key: ((((mytable.vector)::integer[])::vector <#> '[1,1,...,1]'::vector))
               Sort Method: top-N heapsort  Memory: 25kB
               Worker 0:  Sort Method: top-N heapsort  Memory: 25kB
               ->  Parallel Seq Scan on mytable  (cost=0.00..80555.82 rows=588231 width=12) (actual time=0.413..15452.274 rows=500000 loops=2)
 Planning Time: 10.502 ms
 Execution Time: 15635.121 ms
(11 rows)

强制2个并行worker的设置及执行计划输出

设置语句:

set force_parallel_mode = on;
set max_parallel_workers = 2;
set max_parallel_workers_per_gather = 2;
set enable_parallel_hash = on;

执行计划:

Limit  (cost=83268.20..83269.37 rows=10 width=12) (actual time=14369.219..14379.656 rows=10 loops=1)
   ->  Gather Merge  (cost=83268.20..180496.59 rows=833328 width=12) (actual time=14369.217..14379.647 rows=10 loops=1)
         Workers Planned: 2
         Workers Launched: 2
         ->  Sort  (cost=82268.18..83309.84 rows=416664 width=12) (actual time=14352.711..14352.714 rows=9 loops=3)
               Sort Key: ((((mytable.vector)::integer[])::vector <#> '[1,1,...,1]'::vector))
               Sort Method: top-N heapsort  Memory: 25kB
               Worker 0:  Sort Method: top-N heapsort  Memory: 25kB
               Worker 1:  Sort Method: top-N heapsort  Memory: 25kB
               ->  Parallel Seq Scan on mytable  (cost=0.00..73264.22 rows=416664 width=12) (actual time=0.611..14204.459 rows=333333 loops=3)
 Planning Time: 7.062 ms
 Execution Time: 14380.487 ms
(12 rows)
疑问与解答

疑问1:执行计划中的行数值与表中实际100万行不符,原因是什么?

  • 计划里的预估行数是基于表的统计信息计算的,可能统计信息过时,或者char[]转vector的类型转换让优化器无法准确预估行数。
  • 实际执行的行数是按worker拆分的总和:第一个计划里Parallel Seq Scan的rows=500000 loops=2,50万×2正好是100万;第二个计划里rows=333333 loops=3,33.3万×3也接近100万,和实际表行数一致。

疑问2:在哪里可以查看点积计算相关的时间估算/实测值?

  • 当前EXPLAIN ANALYZE输出中,Parallel Seq Scan的实际时间(比如actual time=0.413..15452.274)就包含了点积计算的时间,因为点积是作为排序键在扫描过程中计算的。
  • 若要更细分,可使用EXPLAIN (ANALYZE, BUFFERS, TIMING),但PostgreSQL不会单独拆分算子耗时,只能通过总扫描时间减去纯扫描开销来估算点积耗时——从数据看,扫描的实际时间绝大部分都花在了类型转换和点积计算上。

疑问3:第二个执行计划输出为何显示12行?

  • 执行计划的行数按节点层级统计:第二个计划启用了2个worker,每个worker的排序信息会单独占一行,比第一个计划多了Worker 1: Sort Method: top-N heapsort Memory: 25kB这一行,所以总数从11行变成12行。

疑问4:执行计划揭示了哪些导致并行化性能未达预期的原因?

  • 类型转换开销大:查询需要把char[]转成int[]再转成vector才能计算点积,这是CPU密集型操作,2vCPU实例算力有限,无法完全发挥并行优势。
  • Gather Merge开销:并行worker完成各自的top-N排序后,主进程需要做合并排序,额外的通信和同步开销抵消了部分并行收益。
  • 硬件资源限制:AWS RDS免费版是2vCPU,启用2个worker后,主进程也要占用CPU资源,每个worker能分到的CPU时间不足,无法实现接近翻倍的性能提升。
  • top-N排序开销:每个worker都要做一次top-N排序,主进程还要合并,这部分串行开销影响了整体并行效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 03:45:14