web-dev-qa-db-ja.com

Postgresはレコードの挿入順序を保持しますか?

たとえば、レコードIDを返すクエリを使用している場合

INSERT INTO projects(name)
VALUES (name1), (name2), (name3) returning id;

出力を生成するもの:

1
2
3

このIDは対応する挿入された値を指しますか?

1 -> name1
2 -> name2
3 -> name3
20
Sergey

この単純なケースの答えははいです。行は、VALUES式に指定された順序で挿入されます。また、id列がserialタイプの場合、基になるシーケンスからの値がその順序でフェッチされます。

ただし、これは実装の詳細であり、保証はありません。特に、WHERE条件または結合を使用したより複雑なクエリでは、必ずしも順序が維持されるとは限りません。

同じテーブルに同時に書き込みを行う同時トランザクションがある場合、ギャップや他の行が混在する可能性もあります。可能性は低いですが、可能です。

データベーステーブルには「自然な」順序はありません。行の物理的な順序(これは システム列ctid に反映されます)は最初は挿入された順序に対応しますが、いつでも変更される可能性があります。 UPDATEDELETEVACUUMなどのコマンドは、行の物理的な順序を変更できます。しかし、生成されたidの値は安定しており、もちろんそれには関連していません。

19

Erwin Brandstetterの回答 場合によっては正しくない可能性があります。

INSERT INTO ... SELECT bar,baz FROM foo ORDER BY barおよびSELECT ctid,* FROM fooは、テーブル内の行の物理的な順序が挿入順序と正確に一致していないことを示しています。少し乱雑に見えます。テーブルには、データサイズが大きく変動するjsonb列があることに注意してください。挿入中にjsonbデータを実験的にトランケートすると、挿入順序が正しくなりました。

3
user2052675