web-dev-qa-db-ja.com

PostgreSQLにファイルを保存する際にパフォーマンスの問題はありますか?

HTMLページ、画像、PDFなどのファイルをPostgreSQLのテーブルに保存しても大丈夫ですか、それとも遅いですか?これは推奨されないという記事をいくつか読んだことがありますが、これが本当かどうかはわかりません。

私が念頭に置いている列の型はBLOB(ファイルに格納されていることがわかっている限り)またはbytea型ですが、他の型も適用可能です。

41
Renato Dinhani

基本的に2つの選択肢があります。行にデータを直接格納することも、ラージオブジェクト機能を使用することもできます。 PostgreSQLは [〜#〜] toast [〜#〜] と呼ばれるものを使用して大きなフィールドをテーブルの外に移動するため、行に大きなデータを直接格納することに伴うパフォーマンスの低下はありません。フィールドのサイズには1 GBの制限があります。これが非常に制限されている場合、またはストリーミングAPIが必要な場合は、ラージオブジェクト機能を使用できます。これにより、データベース内のファイル記述子のようなものが得られます。 LO IDを列に格納し、そのIDから読み取りと書き込みを行うことができます。

個人的には、絶対に必要な場合を除いて、ラージオブジェクト機能を使用しないことをお勧めします。 TOASTを使用すると、ほとんどのユースケースは、データベースを期待どおりに使用するだけでカバーされます。ラージオブジェクトを使用すると、使用したLO IDを追跡し、使用されなくなったとき(以前ではない)にリンクを解除する必要があるため、メンテナンスの負担が増えます。永久に領域を占有するデータディレクトリ。また、周りに並外れた動作をする施設もたくさんあります。私がそれらを使用することはないので、その詳細は私を逃れます。

ほとんどの人にとって、データベースへの大きなデータの格納に伴う大きなパフォーマンスのペナルティは、特に指示しない限り、ORMソフトウェアがすべてのクエリでビッグデータを引き出すことです。これらの列を大きなものとして扱い、特別に要求されたときにのみフェッチするために、Hibernateまたは使用しているものに注意する必要があります。

59
Daniel Lyons

BLOB(LO)タイプは、標準のPostgreSQLヒープページ内の2KBのチャンクにデータを格納します。デフォルトのサイズは8KBです。それらは、ファイルシステムに独立したまとまりのあるファイルとして保存されません。たとえば、ファイルを特定できず、バイトごとの比較を実行して、元のファイルデータと同じであることが期待されます。チャンクを区切るPostgresヒープページヘッダーと構造体もあるので、データベースにロードされます。

アプリケーションでバイナリデータを頻繁に更新する必要がある場合、特にPostgreSQLの同時実行制御(MVCC)の実装方法が原因で、大量の小さなランダムアクセス書き込みが含まれる場合は、ラージオブジェクト(LO)インターフェイスの使用を避けてください。データベースをVACUUMするまで、使用されるディスク容量が急激に増える可能性があります。同じ結果はおそらく、bytea型またはTOASTされた列にインラインで格納されたデータにも当てはまります。

ただし、データがWrite-Once-Read-Manyパターンに従う場合(たとえば、PNG画像をアップロードし、後で変更しないこと)、ディスク使用の観点からは問題ありません。

詳細については このpgsql-generalメーリングリストスレッド を参照してください。

14
singularsyntax