web-dev-qa-db-ja.com

PostgreSQL Upsertがパーティションテーブルで機能しない

次のようなテーブルがあります。

CREATE TABLE aggregated_master (
  "user"       BIGINT,
  type         TEXT,
  date         TIMESTAMP,
  operations   BIGINT,
  amount       NUMERIC,
  PRIMARY KEY ( "user", type, date )
);

このテーブルは、多くのパーティションが継承するマスターです。パーティションは、DATEフィールドのMONTHによって行われます。たとえば、Aug-2017のパーティションはagg_201708で、そのPKはpk_agg_201708になります。挿入を適切なパーティションにリダイレクトする通常のトリガーBEFORE INSERTがあります。

事は私がこのテーブルにUPSERTをしたいということです。 DO CONFLICT部分が機能していません。

最初のコードはこのようなものでした

INSERT INTO aggregated_master (user, type, date, oeprations, amount)
SELECT user, type, date, SUM(ops), SUM(amt)
FROM ...
WHERE ...
GROUP BY USER, TYPE, DATE
ON CONFLICT ON CONSTRAINT pk_aggregated
DO UPDATE SET operations = EXCLUDED.operations
          ,   amount = EXCLUDED.amount

しかしその後、制約(pk_aggregated)がマスターテーブルの制約であり、トリガーが原因で実際​​に挿入が実行される子テーブルの制約ではないことに気付きました。

CONFLICT句を次のように変更しました。

ON CONFLICT (user, type, date)

これはPKのフィールドですが、これも機能しません。

これを機能させる方法はありますか?

9
Sergi Porta

PostgreSQL 11は、パーティションテーブルでINSERT INTO ... ON CONFLICTをサポートしています。

CREATE TABLE o(id INT PRIMARY KEY, i INT) PARTITION BY RANGE (id);

CREATE TABLE o1 PARTITION OF o FOR VALUES FROM (1) TO (1000);
CREATE TABLE o2 PARTITION OF o FOR VALUES FROM (1000) TO (2000);

INSERT INTO o(id, i) VALUES (1,1),(2,2),(1500,1500);

INSERT INTO o(id, i)
VALUES (1500, 1400), (2,20), (3, 3)
ON CONFLICT (id)
DO UPDATE SET i = EXCLUDED.i;

SELECT * FROM o;

DBFiddleデモ


制限 ddl-partitioning

5.10.2.3。制限事項

パーティション化されたテーブルでON CONFLICT句を使用すると、エラーが発生します。一意制約または除外制約は、個々のパーティションでのみ作成できるためです。パーティション階層全体で一意性(または除外制約)を適用することはサポートされていません。

解除されました。

6
lad2025

Postgres 11より前のバージョンでは、パーティションテーブルのアップサートは実装されていません。

Postgres 9.6の場合:

ON CONFLICT句を含むINSERTステートメントは期待どおりに機能しない可能性があります。ONCONFLICTアクションは、指定されたターゲットリレーションで一意の違反が発生した場合にのみ実行され、その子リレーションでは発生しないためです。

宣言的なパーティション分割では問題は解決されません、 Postgres 10:

パーティション化されたテーブルでON CONFLICT句を使用すると、エラーが発生します。一意制約または除外制約は、個々のパーティションでのみ作成できるためです。パーティション階層全体で一意性(または除外制約)を適用することはサポートされていません。

Workaround

Postgres 11ではON CONFLICTパーティションテーブルについては、 lad2025の回答を参照してください。

11
klin