PostgreSQLへの画像の保存


111

了解しました。そこで、フロントエンドがほとんど問題にならないはずですが、PostgreSQLを実行するLinuxバックエンドを使用して、フロントエンドがC#.NETで記述されたWindowsボックスに画像を提供するアプリケーションに取り組んでいます。私の質問は:

  • Postgresに画像を保存するための最良の方法は何ですか?

画像のサイズはそれぞれ約4〜6メガピクセルで、3000以上を格納しています。これはWebアプリケーションではなく、一度にデータベースにアクセスするフロントエンドが最大で2つ程度あることにも注意してください。

回答:


64

2012年に更新すると、すべてのアプリケーションで画像のサイズと画像の数が増加し続けていることがわかります...

サムネイルのように、「元の画像」と「処理された画像」を区別する必要があります。

Jcobyの答えが言うように、2つのオプションがあります。

  • 使用BLOB(バイナリラージオブジェクト):元の画像の保存のために、あなたのテーブルで。Ivanの回答(blobのバックアップに問題はありません!)、PostgreSQLの追加提供モジュールハウツーなどを参照してください。

  • DBlinkで別のデータベースを使用する:別の(統一された/専門化された)データベースで、元の画像ストア用。この場合、私はbyteaを好みますが、ブロブ はほぼ同じです。データベースの分離は、「統合イメージWebサービス」の最良の方法です。

  • bytea(BYTE配列)を使用:サムネイル画像をキャッシュします。小さな画像をキャッシュしてWebブラウザーにすばやく送信し(レンダリングの問題を回避するため)、サーバーの処理を減らします。幅や高さなどの重要なメタデータもキャッシュします。データベースキャッシングが最も簡単な方法ですが、ニーズとサーバー構成(Apacheモジュールなど)を確認してください。サムネイルをファイルシステムに保存する方が良い場合があります。パフォーマンスを比較してください。これは(統合された)Webサービスであり、別のデータベース(バックアップなし)に保存して、多くのテーブルにサービスを提供できることに注意してください。PostgreSQLのバイナリデータ型のマニュアルbyteaカラムを使用したテストなどもご覧ください。

注1:現在、「デュアルソリューション」(データベース+ファイルシステム)の使用は非推奨(!)です。デュアルの代わりに「データベースのみ」を使用することには多くの利点があります。PostgreSQLは同等のパフォーマンスとエクスポート/インポート/入力/出力のための優れたツールを備えています。

注2:PostgreSQLが唯一持っていることを覚えておいてくださいbytea型をデフォルトのOracleの持っていない、BLOBを:「(...)SQL標準の定義BLOBを入力書式はbyteaと異なりますが、提供される機能および演算子はほとんど同じです」、マニュアル


EDIT 2014:私は今日以上の元のテキストを変更していない(私の答えは今、14票で4月22日'12、だった)、私はあなたの変更のための答えを開封しております (編集することができ、「ウィキモード」を参照してください!)、のためのプルーフリーディング更新のため
質問は安定しています(@Ivansの'08回答、19票)。このテキストの改善にご協力ください。


2
「...「デュアルソリューション」(データベース+ファイルシステム)の使用は廃止される...」のリファレンスは何ですか?
dangel

2019年のニュース 2018年以降、 PostgRESTはウェブへのbyteaの直接出力をサポートしています。使用するには、このNGINXのシンプルな構成を参照してください。バイナリ出力に関するPostgRESTガイドを
Peter Krauss

52

jcobyの答え:

byteaが「通常の」列であることは、フェッチ時に値がメモリに完全に読み込まれることも意味します。対照的に、ブロブはstdoutにストリーミングできます。これにより、サーバーのメモリフットプリントを削減できます。特に、4-6 MPix画像を保存する場合。

blobのバックアップに問題はありません。pg_dumpは、「-b」オプションを提供して、ラージオブジェクトをバックアップに含めます。

ですから、私はpg_lo_ *を使用することを好みます。

クリス・エリクソンの答え:

私は反対を言うでしょう:)。保存するデータが画像だけではない場合は、どうしても必要な場合を除いて、ファイルシステムに保存しないでください。データの一貫性を常に確認し、データを「1つに」(DB)持つことは、このような利点です。ところで、PostgreSQLは一貫性の維持に優れています。

ただし、実際には、多くの場合、パフォーマンスは要求が厳しすぎる;-)ため、ファイルシステムからバイナリファイルを提供する必要があります。しかし、それでも私は、DBをバイナリの「マスター」ストレージとして使用する傾向があり、他のすべての関係は一貫してリンクされ、パフォーマンスの最適化のためにファイルシステムベースのキャッシュメカニズムを提供しています。


14
10年後、あなたのポイントはまだ有効だと思いますか?それ以降の更新はありますか?
leventunver 2018年

3
@leventunverいいえ、保持すべきではないポイント。たとえばBYTEA、「通常の」列であることの最初の例です。Postgresは何年もの間、列への、または列からのストリーミングをサポートしてきましBYTEAた。つまり、コンテンツをデータベースに保存する前に、メモリに保存する必要はありません。
オリゴフレン2019年

29

データベースには、次の2つのオプションがあります。

  • bytea。バックアップの一部としてエクスポートされたデータを列に格納します。標準のデータベース関数を使用して、保存および取得します。あなたのニーズにお勧めします。
  • ブロブ。データを外部に保存します。通常、バックアップの一部としてエクスポートされません。保存および取得するには、特別なデータベース関数が必要です。

私は過去に何千行もの10 + GBの画像を保存することで大きな成功を収めたbytea列を使用しました。PGのTOAST機能は、ブロブが持つ利点をほとんど無効にします。どちらの場合も、ファイル名、コンテンツタイプ、ディメンションなどのメタデータ列を含める必要があります。


1
10GBはそれほど多くありません:-(私はTBソリューションを探しています
Valentin Heinitz 2017年

2
@ValentinHeinitz TBの場合、バニラPostgresはテキスト列が小さくても苦労します。
sudo 2017

23

2015年半ばへのクイックアップデート:

Postgres外部データインターフェイスを使用して、ファイルをより適切なデータベースに保存できます。たとえば、MongoDBの一部であるGridFSにファイルを配置します。次に、 https://github.com/EnterpriseDB/mongo_fdw を使用してPostgresでそれにアクセスします。

これには、PostrgresとMongoDBでアクセス/読み取り/書き込み/バックアップできるという利点があります。柔軟性に応じて異なります。

ファイルシステム用の外部データラッパーもあり ます。https //wiki.postgresql.org/wiki/Foreign_data_wrappers#File_Wrappers

例として、これを使用できます:https : //multicorn.readthedocs.org/en/latest/foreign-data-wrappers/fsfdw.html (簡単な使用例については、こちらを参照してください)

これにより、一貫性(すべてのリンクされたファイルが確実に存在する)と他のすべてのACIDの利点が得られますが、実際のファイルシステムにはまだ存在します。つまり、必要なファイルシステムを使用でき、ウェブサーバーが直接提供できますOSキャッシュも適用されます)。


1
ありがとう..外部データラッパー(file_fdw)は、画像への書き込みアクセスを提供しますか?画像をFileSystemとそのメタデータにPostgresqlに保存したいのですが、一貫性も維持する必要があります。詳細な解決策はありますか?他に利用可能な拡張機能はありますか?... Multicornのpythonを必要とし、私は、Pythonを使用せずに行うことを持つことを好むだろう
ジェイKhatwani

1
はい、書き込みアクセス権があります。それらは両方向から完全に一貫しています。そして、Pythonなしでこれを行う同等のソリューションを知りません。
Kenyakorn Ketsombut 2016年

18

10年後の更新 2008 年にデータベースを実行するハードドライブは、ファイルを保存するディスクとは大きく異なる特性とはるかに高いコストになります。最近では、10年前には存在しなかったファイルを保存するためのより良い解決策があり、私はこのアドバイスを取り消し、読者にこのスレッドの他の回答のいくつかを見るようにアドバイスします。

元の

どうしても必要な場合を除いて、データベースに画像を保存しないでください。これはウェブアプリケーションではないことを理解していますが、共有ファイルの場所がない場合は、ファイルの場所をデータベースに保存するように指定できます。

//linuxserver/images/imagexxx.jpg

そうすれば、おそらくWebサーバーをすばやくセットアップして、WebのURL(およびローカルパス)をデータベースに保存できます。データベースはLOBと3000の画像(4K〜6メガピクセル、画像を500Kと想定)を処理できますが、1.5ギガは多くのスペースを備えていません。


15
しかし、ファイルをいくつかのディレクトリに分散する方法を考え出す必要があります。ファイルシステムは、単一のディレクトリに数百万のファイルを保存するのがあまり得意ではありません(実際には、すでに1万件が問題になっています)
a_horse_with_no_name 2013年

1
元の質問には答えません。SQLを抽象化のレイヤーとして使用し、ext4ファイルシステム内のファイルを管理したくないという理由だけで、私は個人的にPostgresにイメージを保存することを考えています。
sudo 2017

私は矛盾しています。これは質問に答えませんが、質問に対する答えよりも良い答えであるため、私はそれを賛成しました。
Andrew Carr

6

これを試してください。生成されたPDFドキュメント(一部はサイズが10 MB以上)をデータベースに格納するために、ラージオブジェクトバイナリ(LOB)形式を使用しました。


2

画像が小さい場合は、プレーンテキストフィールドにbase64として保存することを検討してください。

その理由は、base64には33%のオーバーヘッドがあり、圧縮はほとんどなくなるためです。(Base64エンコーディングのスペースオーバーヘッドとは何ですか?)データベースは大きくなりますが、Webサーバーがクライアントに送信するパケットは大きくなりません。HTMLでは、base64を<img src = "">タグでインライン化できます。これにより、別のブラウザーフェッチでバイナリとして画像を提供する必要がないため、アプリを簡略化できる可能性があります。画像をテキストとして処理すると、jsonを送受信する必要があるときにも簡単になります。これは、バイナリをうまく処理できないためです。

はい、バイナリをデータベースに保存し、データベースに出入りする途中でテキストとの間で変換できることを理解しましたが、ORMが面倒なこともあります。他のすべてのフィールドと同様に、単純なテキストとして扱うだけの方が簡単です。

これは間違いなくサムネイルを処理する正しい方法です。

(OPの画像は小さくないので、これは彼の質問に対する答えではありません。)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.