【问题标题】:PosgreSQL INSERT ON CONFLICT sometimes does not work with partial indexPostgreSQL INSERT ON CONFLICT 有时不适用于部分索引
【发布时间】:2023-02-05 05:09:59
【问题描述】:

例子:

CREATE TABLE IF NOT EXISTS test
(
    type character varying,
    id   integer
);

CREATE UNIQUE INDEX IF NOT EXISTS uniq_id_test 
    ON test USING btree (type, id) 
    WHERE (type = 'Test');

PREPARE test (text, int, text) AS
    INSERT INTO test (type, id)
    VALUES ($1, $2)
    ON CONFLICT (type, id)
    WHERE type = $3 DO
    UPDATE
    SET id = EXCLUDED.id;


EXECUTE test('Test', 1, 'Test');
EXECUTE test('Test', 2, 'Test');
EXECUTE test('Test', 3, 'Test');
EXECUTE test('Test', 4, 'Test');
EXECUTE test('Test', 5, 'Test');
EXECUTE test('Test', 6, 'Test');

最后一个 EXECUTE 语句总是抛出一个错误:

[42P10] 错误:没有匹配 ON CONFLICT 规范的唯一或排除约束

如果我们 DEALLOCATE 准备好的语句然后重新创建它,我们将有另外 5 次成功尝试,并且在第 6 次尝试时我们将再次出现上述错误。

如果我们用常量值 'Test' 替换 $3 参数(没有错误),所有这些都可以正常工作:

PREPARE test (text, int, text) AS
    INSERT INTO test (type, id)
    VALUES ($1, $2)
    ON CONFLICT (type, id)
    WHERE type = 'Test' DO
    UPDATE
    SET id = EXCLUDED.id;

因此,据此,我可以假设根本原因是我在INSERT ON CONFLICT WHERE 准备语句中使用了参数而不是常量,并且 plancacher 或 smth 无法正确使用它。但我希望看到对上述问题的更详细解释,因为我不是数据库专家,也不明白为什么它会以这种方式工作......

PG版本:

PostgreSQL 13.9 (Debian 13.9-1.pgdg110+1) on x86_64-pc-linux-gnu, 
compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit

【问题讨论】:

  • 我要说这是由于:.当前的规则是前五次执行是使用自定义计划完成的,并计算这些计划的平均估计成本。然后创建一个通用计划,并将其估计成本与平均定制计划成本进行比较。如果后续执行的成本不比定制计划的平均成本高很多,那么重复的重新计划似乎更可取,则后续执行将使用通用计划。来自这里Prepare
  • 如果通用计划导致查询被破坏的情况,它不是一个错误吗?
  • 首先确定这是问题所在。见笔记Prepare 链接的部分我之前发布的有关如何强制执行通用或自定义计划的信息。如果这是一个问题,我会在这里建议任何一个错误报告文件Bug请注意,您将需要一个社区帐户或在pgsql-general 邮件列表上询问。

标签: sql postgresql sql-insert


【解决方案1】:

那是因为从第六次执行开始,PostgreSQL 使用了通用计划对于这个准备好的声明。这样的通用计划不使用参数值。其背后的想法是避免为每次执行重新规划语句。因此,$3 的值是未知的,无法推断出部分索引。

您可能会说这是邮件列表中的错误,但我怀疑它是否会被接受。

您可以使用的解决方法是通过设置 plan_cache_mode = force_custom_plan 来避免通用计划。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    • 2016-05-06
    • 1970-01-01
    • 2017-05-28
    • 2023-02-04
    相关资源
    最近更新 更多