web-dev-qa-db-ja.com

Postgresで、主キーが外部キーでもある場合

Postgres 12では、写真を追跡しています。それぞれが大きく、それぞれ約6〜8 MBです。簡単に閲覧できるように、サムネイル画像を画像全体とともに保存します。フルとサムネイルの両方がBYTEAタイプの列です。

パフォーマンスのために、サムネイルのみが必要なときに画像全体をロードすることは避けたいです。私が理解しているように、行にアクセスすると、すべてのBYTEAフィールド値がメモリにロードされます。したがって、ユーザーにサムネイルのリストを表示すると、クエリで明示的に要求されていない場合でも、サーバーに完全な写真が読み込まれます。

したがって、その写真テーブルを2つに分割し、サムネイルをメインテーブルに格納し、サムネイルを個別の子テーブルに1対1で格納します。

このようなシナリオでは、子のフル写真テーブルは、親のサムネイル行のIDを外部キーとして保持します。その外部キー列は、論理的に主キーとしても機能します。

子の1つの列を外​​部キーと主キーの両方に指定できますか?もしそうなら、注意すべき注意点はありますか?

4
Basil Bourque

主キーと外部キー

子の1つの列を外​​部キーと主キーの両方に指定できますか?

そのとおり:

create table photo 
(
  id integer primary key, 
  ... other columns ...
);

create table thumbnail 
(
  id integer primary key references photo, 
  ... other columns ...
);

トースト

bytea列は通常の列データ(いわゆる "トーストテーブル" )の外部に格納され、それらをSELECTリストに含めない限り取得されません。

マニュアルからの引用

TOASTされた属性の大きな値は、結果セットがクライアントに送信されたときにのみ引き出されます(選択されている場合)。

これは、クエリがSeq Scanを実行するように強制されている場合でも、送り返す必要がある行が識別されるまでbytea列が取得されないことを意味します。したがって、クエリが100万行でseqスキャンを実行したが、1行しか返されなかった場合、bytea値が1つだけ読み取られてクライアントに送信されます。

サムネイルが十分に小さい場合、サムネイルは実際にはインラインで(トーストテーブルではなく)保存される可能性があることに注意してください(約2k未満のサイズの場合にのみトーストがトリガーされます)

列は個別にトーストされるため、両方の画像を1つのテーブルに保持しても問題はありません。 SELECTリストに表示される画像のみがデトーストされます。

さらに、UPDATEがトーストされた列に影響を及ぼさない場合、それらを書き換える必要はありません。

1
Laurenz Albe