在 postgres 中查询计划在运行时更改

Query plan changes at runtime in postgres

我有两个简单的 tables:

Profile (20M entries)
----------------------------
pId | fail 
123 | 0
234 | 2
345 | 0

Work (50M entries)
-----------------
pId
123
234
123
345
123
345

我只想在 Profile 中将 fail 标记为 1 table 对于 Work 中超过阈值 pId 的条目table。 Profile table 中的 pId 已编入索引,我不想触及 fail 不是 0.

的行

我现在使用的查询是:

UPDATE Profile 
SET fail = 1 
WHERE pId IN 
    (
      SELECT pId 
      FROM Work 
      GROUP BY pId 
      HAVING COUNT(*) > 2
    )
AND Profile.fail = 0;

在 pgAdmin 中,我得到如下解释计划:

"Update on Profile a  (cost=1134492.79..1559750.23 rows=5180 width=1014)"
"  ->  Hash Join  (cost=1134492.79..1559750.23 rows=5180 width=1014)"
"        Hash Cond: (a.pId = b.pId)"
"        ->  Seq Scan on Profile a  (cost=0.00..425216.00 rows=15462 width=976)"
"              Filter: (fail = 0)"
"        ->  Hash  (cost=1134491.95..1134491.95 rows=67 width=32)"
"              ->  Subquery Scan on b  (cost=1134488.78..1134491.95 rows=67 width=32)"
"                    ->  HashAggregate  (cost=1134488.78..1134491.28 rows=67 width=4)"
"                          Group Key: Work.pId"
"                          Filter: (count(*) > 5)"
"                          ->  Seq Scan on Work  (cost=0.00..894341.52 rows=48029452 width=4)"

运行 需要几分钟。

现在,当这两个 table 在 运行 时使用相同的数据创建时,查询计划更改为:

"Update on Profile  (cost=1250747.42..1251317.47 rows=67 width=386)"
"  ->  Nested Loop  (cost=1250747.42..1251317.47 rows=67 width=386)"
"        ->  Subquery Scan on "ANY_subquery"  (cost=1250746.98..1250750.15 rows=67 width=32)"
"              ->  HashAggregate  (cost=1250746.98..1250749.48 rows=67 width=4)"
"                    Group Key: Work.pId"
"                    Filter: (count(*) > 5)"
"                    ->  Seq Scan on Work  (cost=0.00..985990.32 rows=52951332 width=4)"
"        ->  Index Scan using Profile_idx on Profile  (cost=0.44..8.46 rows=1 width=348)"
"              Index Cond: (pId = "ANY_subquery".pId)"
"              Filter: (fail = 0)"

运行 需要一个小时。我什至尝试过从子查询切换到连接,但它仍然产生相同的结果。任何帮助将不胜感激。

你的问题的关键可能是:

Now when these two tables are created at runtime with the same data, the query plan changes to [the worse]

PostgreSQL 自动收集 table 统计数据,但自动分析需要一段时间才能启动。

在批量数据修改和自动分析完成之间 运行 的所有查询都可能有错误的执行计划。

在大量数据修改结束时 table 显式 运行 ANALYZE 是个好主意。