请求不更新行但 returns 成功

Request not updating rows but returns successful

我正在尝试从另一个更新 table,请求最终成功,但没有更新任何行。每个 table 包含 ~32M 行。 我 运行 使用 PostgreSQL 11.12。

这是 2 table(我删除了请求中未使用的列):

CREATE TABLE IF NOT EXISTS public.sirene_geo
(
    siret character varying(50) NOT NULL,
    x numeric,
    y numeric,
    CONSTRAINT sirene_geo_etablissement_pkey PRIMARY KEY (siret)
)

CREATE TABLE IF NOT EXISTS public.sirene_eta
(
    siret character varying(50) NOT NULL,  
    latitude numeric,
    longitude numeric,
    CONSTRAINT sirene_stock_etablissement_pk PRIMARY KEY (siret)
)

更新请求:

UPDATE sirene_eta eta
SET longitude = x,
    latitude = y
FROM sirene_geo geo
WHERE eta.siret = geo.siret

在 pgAdmin (v5.4) 上,“受影响的行”字段显示为 -1。
Postgres 是使用 hash join 策略来完成更新的。 此外,sirene_geo 中的行数少于 sirene_eta,Postgres 仍在 sirene_geo 上构建散列 table(因此导致某些行不匹配)。

当我尝试在子查询 table 内进行限制更新时,它可以工作,但它使用绝对不是 suitable 的嵌套循环策略来更新整个 table。

更新:
没有并发写入 activity。我检查了日志,确实有一个错误:

ERROR: could not write to file "base/pgsql_tmp/pgsql_tmp9264.8256": No space left on device

您的存储设备上 space 已 运行 次。 在启动大 UPDATE 之前,在磁盘上腾出空间(或任何你用作存储的东西)。删除可有可无的文件(与数据库无关)。或者以某种方式缩小你的数据库。

普通的 VACUUM 可能 可以胜任。或者 VACUUM FULL(阻止并发访问)以积极缩小物理存储。如果您无法阻止,请考虑使用 non-blocking 社区工具之一。参见:

  • Optimize Postgres query on timestamp range

VACUUM FULL 最好在 sirene_eta(目标 table)上 not 无论如何都会重用 UPDATE 中的死元组(在普通 VACUUM 之后)。并确保 VACUUM 没有被长 运行 事务阻塞。参见:

无论您做什么,如果您不希望 all 目标行实际发生变化,请添加 WHERE 条件来过滤空更新(全额付费! )

UPDATE sirene_eta eta
SET    longitude = geo.x
     , latitude  = geo.y
FROM   sirene_geo geo
WHERE  eta.siret = geo.siret
AND   (eta.longitude IS DISTINCT FROM geo.x  -- !
    OR eta.latitude  IS DISTINCT FROM geo.y)

甚至可以通过减少要完成的工作(显着)来解决您的问题。 (事实证明,你的情况并非如此。

参见:

  • How do I (or can I) SELECT DISTINCT on multiple columns?