web-dev-qa-db-ja.com

バイナリファイルをデータベースに保存する必要がありますか?

データベースのデータに関連するバイナリファイルを保存するのに最適な場所はどこですか?あなたは:

  1. Blobを使用してデータベースに保存する
  2. データベース内のリンクを使用してファイルシステムに保存する
  3. ファイルシステムに保存しますが、コンテンツのハッシュに名前変更して、データベースに保存します
  4. 思いもしなかったこと

(1)の利点は(とりわけ)トランザクションの原子性が保持されることです。コストは、ストレージ(および関連するストリーミング/バックアップ)の要件を劇的に増やす可能性があることです。

(3)の目的は、原子性をある程度維持することです-書き込み先のファイルシステムでファイルの変更や削除を許可せず、常にファイル名として正しいハッシュを使用できる場合。アイデアは、ハッシュを参照する挿入/更新を許可する前にファイルシステムにファイルを書き込むことです。このトランザクションがファイルシステムの書き込み後、データベースのDMLの前に失敗した場合、ファイルシステムがすべてのリポジトリであるように見えるため、問題ありません。可能なファイルとハッシュ-そこにポイントされていないファイルがいくつかあるかどうかは問題ではありません(注意して定期的にクリーンアップすることもできます)

編集:

一部のRDBMSはこれを個別の方法でカバーしているようです-特に他の方法で知りたい-特にpostgresのソリューションで知りたい

  1. blobを使用してデータベースに保存

    欠点は、データベースファイルが非常に大きくなり、既存のセットアップでバックアップするには大きすぎることです。利点は、整合性と原子性です。

  2. データベースにリンクされたファイルシステムに保存

    このような恐ろしい災害に遭遇したので、人々が提案し続けるのは恐ろしいことです。いくつかの災害が含まれています:

    • ファイルを再配置し、DB内のパスと現在のパスとの間のリンクを頻繁に切断する1人の特権ユーザー(ただし、どういうわけかこれは私の責任となりました)。
    • あるサーバーから別のサーバーに移動すると、古いマシンの管理者アカウント(古いWebサイトが実行されていたアカウント)のSIDがドメインの一部ではなかったため、一部のファイルの所有権が失われました。解決されないため、ユーザーにユーザー名/パスワード/ドメインログインプロンプトが表示されます。
    • 一部のパスはC:\から.docまでの256文字より長くなり、すべてのバージョンのNTが長いパスを処理できませんでした。
  3. ファイルシステムに保存しますが、コンテンツのハッシュに名前変更して、データベースに保存します

    私が働いた最後の場所は、上記のシナリオの私の説明に基づいてこれを行いました。彼らは、組織が大規模なデータベースの経験を得ることができない(約40Gを超えるものは「大きすぎる」と定められている)こと、企業が大容量のハードドライブを購入できないこと、およびより近代的なバックを購入できないことの間の妥協であると考えました。アップソリューション、および上記で特定したリスク#1と#3から逃れる必要性。

私の意見では、DBにblobとして保存する方が、特にフェイルオーバーと可用性の問題があるマルチサーバーシナリオではより優れたソリューションであり、よりスケーラブルです。

61
Tangurena

完全なデータ整合性のための1番。データ品質を気にしない場合は、他のオプションを使用してください。とても簡単です。

ほとんどのRDBMSには、とにかくBLOB(SQL Serverファイルストリームなど)を格納するための最適化があります。

29
gbn

Oracleの場合は、dbfsとSecure Filesを参照してください。

Secure Filesがすべてを説明し、すべてのデータをデータベースに安全に保管します。ロブに編成されています。セキュアファイルは、アクティブ化する必要があるlobの最新バージョンです。

dbfsはデータベース内のファイルシステムです。 Linuxホスト上で、ネットワークファイルシステムのようにマウントできます。それは本当に強力です。 ブログ を参照してください。特定のニーズに合わせて調整するためのオプションもたくさんあります。私はdbaであり、ファイルシステム(データベースに基づいており、Linuxにマウントされている)を指定して、問題なくOracleデータベースを作成しました。 (...データベースに保存されたデータベース)。これが非常に役立つわけではありませんが、それは力を示しています。

その他の利点は、可用性、バックアップ、リカバリ、他のリレーショナルデータと一貫性のあるすべての読み取りです。

データベースにドキュメントを保存しない理由として、サイズが指定される場合があります。そのデータはおそらく何らかの方法でバックアップする必要があるため、データベースに保存しないのは適切な理由ではありません。特に、古いドキュメントが読み取り専用と見なされる状況では、データベースの大部分を読み取り専用にすることは簡単です。その場合、データベースのそれらの部分は、高頻度のバックアップを必要としなくなります。

データベースの外部の何かへのテーブル内の参照は安全ではありません。操作可能で、確認が難しく、簡単に迷子になる可能性があります。トランザクションはどうですか?データベースはこれらすべての問題の解決策を提供します。 Oracle DBFSを使用すると、データベース以外のアプリケーションにドキュメントを提供でき、データベースアプリケーションを使用していることすらわかりません。

最後の大きな驚きですが、dbfsファイルシステムのパフォーマンスは、通常のファイルシステムよりも優れていることがよくあります。これは、ファイルが数ブロックよりも大きい場合に特に当てはまります。

22
ik_zelf

ここでの正しい答えは、アプリケーション、およびそれらのドキュメントの重要性に大きく依存すると思います。

ドキュメント管理システム、または保存されたドキュメントの回復可能性が重要なシステム(ほとんどの場合、財務、人事、CRM関連)の場合、ドキュメントをインラインで保存するか、お気に入りのDBベンダーの独自のドキュメントテクノロジーを使用することは、正しいことのようです。

ただし、反対の決定が適切であると私が考える多くのアプリケーションがあります。

ヘルプデスクシステムとwikiタイプのシステムは、データベースのデータoutを保持することが非常に理にかなっていると思います。 Jiraのように、ドキュメントをインラインで保存するかどうかを選択するオプションを実際に提供しているものもあると思います。

中規模の企業では、チケットシステムのドキュメントをインラインで保存すると、メガバイト単位で測定された圧縮バックアップとギガバイト単位で測定された圧縮バックアップの違いを意味する場合があります。

個人的には、チケットシステムを数分でオンラインに戻し、数時間の間(一般的にはそれほど重要ではない)文書と格闘する方が、「壊れてCTOが首をかしげている」RTOを復元するよりも増やすことを望みます。はるかに大きなバックアップからログを再生します。

ドキュメントを分離しておくことには、他にも利点があります。

  • ドキュメントメタデータのカタログ化、ウイルススキャンの実行、キーワードのインデックス付けなどを行う個別のプロセスを簡単に実行できます。
  • Rsync、ストレージスナップショットなど、データベースよりもファイルに適しているバックアップまたはリカバリを支援するツールを利用できます。
  • 実際には、圧縮または重複排除をサポートするストレージを使用できます(SAN管理者が何年もの間大騒ぎしてきたもの、世界中のデータベース管理者の悩みの種)
  • 複数のサイトにまたがるインストールの場合、中央集中型データベースを分散ファイルシステムで補完できます。

#2と#3のハイブリッドの組み合わせが賢いかもしれません。元のファイル名を保持しますが、ドキュメントのハッシュ/チェックサムを計算して保存します。これにより、誰かがファイルを移動または名前変更した場合の回復に役立つ参照ポイントが得られます。

ファイルを元のファイル名で保存すると、アプリケーションは文字通りファイルシステムから直接ファイルをヤンクして、ネットワーク経由で送信したり、シッククライアントの世界で送信したりできます。ユーザーを直接ファイルサーバーに向けることもできます。

15
Nathan Jolly

しないでください。

データベースにファイルを保存するメリットはありません。

自分で考えたとき、それはすでに奇妙で怪しげな感じではありませんか?

ファイルをデータベースまたはfilesystemに保存する必要がありますか?

さらに良いことに、大声でそれを言ってください。

事実について:

データベースの使用

"[〜#〜] pros [〜#〜]" ...しかし完全ではない

  • 「原子性」は正しいですが、それは両刃の剣です。それはそれと共に短所を引きずるからです。
  • 誠実さ。同上。

バイアスをかけたくありませんが、これ以上追加することはないと思います。あなたがそれについて考えるならば、プロは本当にそれほどよくありません。

以下のコメントを忘れた場合は、その間も以下をお読みください。

短所:

  • ジョブの間違ったツール
  • 維持が難しい
  • スロー
  • 数百MB /ギガバイトのデータPER userの保存を忘れます。
  • 急速に成長しているサイトのバックアップは悪夢になります。
  • 復元/移動も問題になります。

ファイルシステムの使用

長所:

  • メンテナンスがはるかに簡単
  • 速い
  • データベースのバックアップはこれとは何の関係もありません
  • 間違いなく移植性が高い*

[〜#〜] cons [〜#〜]

  • 無し*

*ファインプリント

今、あなたは自分自身に尋ねているのですが、長所は短所がないということですか?どうして?

ここでの最大の間違いは、人々がハンマーでねじをねじ込もうとしていることです。

onlyこれが尋ねられている理由は、ファイルリンクのためです

これは、データベースが解決することを意図していない問題です。あなたがそれについて考えるならば、それは愚かにさえ聞こえます。

「データベースは私のファイルリンクの問題を修正します。」

実際には、論理的にアプリケーションが実際にの処理と提供を担当する必要があります-)リンク。

解決策:

  1. アプリケーションでカスタムルートを使用してURLリクエストを処理します。
  2. このルートをデータベースに保存します。
  3. 内部的には、このルートが呼び出されるたびに、必要なファイルにマップします。
  4. ファイルを別の場所に移動した場合は、ルートのファイル名の値を変更するだけで、そのルートがWeb全体のどこに保存または参照されていても、そのルートは常に同じファイルを提供します。

これにより、ネイティブパスが抽象化され、アプリケーションの移植性、保守性が向上し、何も壊すことなくあらゆる種類のファイルシステムに切り替えることができます。

実装方法はこの回答の範囲外ですが、おそらく最も広く使用されているWeb言語(PHP)の一般的な例を見ることができます。

https://github.com/symfony/Routing

https://github.com/kriswallsmith/assetic

これらは両方とも非常に強力です。

14
Tek

トレードオフについてここに私の経験を追加したいと思います。 PostgreSQLでは、少なくとも、パフォーマンスへの影響はdbサーバーの観点からはごくわずかです。大きなblobは、メインヒープテーブルではなく、個別のファイルに格納され、多数のレコードをカウントする可能性のある操作の邪魔にならないように移動されます。他のデータベースも同様のことをするかもしれません。

主な利点は、原子性とバックアップの目的で、すべての関連データを1か所に保持できることです。これにより、問題が発生する可能性が大幅に減少します。

主な欠点は、上記で取り上げたものではなく、それがフロントエンドでのメモリ使用量です。すべてのdbがこれをどのように処理するか正確にはわかりません。これは実装に依存する可能性がありますが、PostgreSQLの場合、データはエスケープされたASCII文字列(おそらく16進数、おそらくインラインエスケープ付き)として)入ります。次に、フロントエンドでバイナリに変換し直す必要があります。これを行うために見た多くのフレームワークでは、値を(参照としてではなく)渡してから、それに基づいて新しいバイナリ文字列を作成します。Perlを使用してこれを計算しました元のバイナリのメモリを何度も使用してしまいました。

評決:ファイルがたまにしかアクセスされない場合、私はデータベースに保存します。それらが頻繁かつ繰り返しアクセスされている場合、少なくともPostgreSQLでは、コストがメリットを上回っていると思います。

9
Chris Travers

ファイルをデータベースに保存しないでください。

市場でRDBMSを実行できるすべての人は例外なく、すでにファイルを保存するためのデータベースをすでに持っており、RDBMS自体がそれを使用しています。そのデータベースはfilesystemです。次に、データベースにファイルを格納することの潜在的な欠点のいくつかと、データベースにファイルを格納するための特定の問題を緩和する要素について説明します。

  • いいえ filehandes データベース内のファイルに対して。これはどういう意味ですか?

    • プログラマートーク:あなたCAN NOT seek(fseek)、非同期アクセス(asyncioまたはepoll)でリソースを管理する機能はありません、 sendfile はありません(カーネルスペースからコピーを保存します)。

    • 実用的なアプリケーション:HTTP2/3を介してビデオまたは画像をクライアントに送信しませんか?データベースにある場合は、最初にクエリを実行する必要があります。クエリがそのファイルを返す場合、そのファイルが次のステップに進む前に、entireクエリが完了するまで待つ必要があります。 Webサーバーとは異なるサーバーにrdbmsを使用する本番環境のインストールでは、firstファイルをストリーミングするのではなく、rdbmsからwebserverにファイルentirelyを転送する必要があります。使って。ただし、トランスポート層がファイルシステムの抽象化(NFSでもサポートする)を提供している場合は、ファイルの半分をシークし、必要以上にファイルをバッファリングせずに、すぐにクライアントへのストリーミングを開始できます。これは、Webサーバー nginxApache 、PureFTP、およびProFTPによって定期的に行われます。

  • RDBMSのダブルコピー。データベースにあるという事実により、2回書き込むことになります。いったん先書きログ(WAL)に入れられ、その後再びテーブルスペースに入れられます。

  • 更新なし、これまで[〜#〜] mvcc [〜#〜] は、何も更新されず、変更を加えて新しくコピーされるだけで、古い行は期限切れ(削除済み)としてマークされます)。ファイルを更新するには、ファイル全体だけでなくrow全体を書き込む必要があります。ファイルシステムもデータジャーナリングを使用してこれを提供できますが、必要になることはほとんどありません。

  • クエリを遅くするためのファイルの読み取りと転送ファイル自体がクエリする必要のある行に格納されている場合、行全体がファイルの転送を待機するか、または2つの別々のクエリを発行する必要があります。

  • メモリ使用 DBクライアント。 DBクライアント(libpq、jdbc、odbc、freetdsなど)などは、クエリをメモリにバッファリングする可能性があります。インメモリバッファーが使い果たされると、ディスクバッファーが起動するか、さらに悪いことに、カーネルにフォールバックしてディスクにページングされることがあります。

  • Query-throttling多くのデータベースは、時間やリソースが多すぎる場合に、クエリを強制終了および取得する機能を提供します。ファイル転送は、どの実装でも項目化されないことに注意してください。そのクエリは3秒後に強制終了されましたか?それとも1秒かかり、バックエンドは2秒かけてファイルを転送しましたか? 「項目別」だけでなく、クエリの99.9%が1 KBを返し、他のクエリが1 GBを返すときに、クエリにかかる時間を効果的にどのように表現しますか

  • No-copy-on-write or de-deduplication XFSとBTRFSは、copy-on-writeと重複排除を透過的にサポートします。これは、どこでも同じ画像を持っている、またはその2つ目のコピーが必要な場合、ファイルシステムがtransparentlyを処理できることを意味します。ただし、ファイルが独立しておらず、行またはストアにある場合、ファイルシステムは重複排除できない可能性があります。

  • Integrity多くの人が整合性について話しています。ファイルシステムの破損、ファイルシステムまたはファイルシステムのコアユーティリティを使用するアプリケーションを検出するのに、何が良いと思いますか?ファイルを連続して、または行外に格納すると、ファイルシステムの破損によってデータベースが不明瞭になります。 xfs_repairは、ファイルシステムまたはハードドライブの破損がある場合の回復に優れています。失敗した場合でも、データフォレンジックを実行する方がはるかに簡単です。

  • クラウドの移行 SANまたはクラウドにファイルを保存する場合は、ストレージの移行がデータベースであるため、さらに困難になります。移行。たとえば、ファイルがファイルシステムに保存されている場合、S3にかなり簡単に移動できます(そして s3fs 透明にすることができます)。

例外

データベースへのファイルの保存には、いくつかの有効な使用例があります。

  • 必要な場合ファイルを段階的に編集する場合。つまり、ファイルを編集することは、文字通りトランザクションの一部です。または、関係(テーブル)のデータ整合性の問題でトランザクションが失敗した場合に、ファイルの編集をロールバックする機能が必要です
  • 必要ファイルシステムがデータで正確にバージョン管理されていることを確認し、それらの同期を維持することでリスクを許容できない場合。
  • データベースが実際にファイルを解析でき、クエリを実行できる場合。たとえばPostgreSQLでは、トポロジはPostGISでのクエリにすることができます。この時点では、それはファイルですが、ストレージダンプではなく、クエリのデータでもあります。

緩和

  • 一部のデータベースには、「外部管理リソース」という概念があり、データベースはディスク上のファイルを非公開で管理します。

  • Oracle SecureFileのように、一部のデータベースは、大きなバイナリオブジェクトを、アウトオブラインまたはアウトオブラインで格納します。これにより、ファイルを書き換えることなく、行を更新できます。

  • Oracleのような一部のデータベースは、WALログなしでMVCを実行し、ファイルを二重に書き込む必要はありません。

  • SQL ServerやOracleなどの一部のデータベースは、ファイルハンドルを持たなくても、ファイルからデータを「ストリーミング」する機能を提供します。これは、データベースクエリとは異なる接続で実行される場合とされない場合があります。ただし、ここで重要なのは、ファイルを(理論的には)ストリーミングできることができる一方で、その機能を使用するプロバイダーによって作成されていない製品の証拠が見つからないことです。たとえば、これを可能にするNGINX/Apacheブリッジはどこにありますか?

  • Oracleは、オプションの重複排除、圧縮、および暗号化を、SecureFileなどの内部LOBストレージを介して提供します。

結論

データベースにファイルを置くときの最悪のシナリオは、パフォーマンスとツールとの互換性のために非常に悪いです。それは常に例外的に実装に依存しています。データベースは決してbetterファイルシステムではなく、ファイルシステムです。あらゆる点で妥協点であり、強力な緩和機能(SecureFileの場合など)を入手したとしても、ツールは貧弱であり、スタック全体がRDBMSプロバイダーによって構築されていない限り、マーケティングポイントにすぎません。

シンプルにしてください。一般的なルールはDBからファイルを除外するです。

解決

複数のテナントやユーザーが効果的に機能するためには、ファイルをどのように保存するか、またはファイルシステムを抽象化してどのようにすべきでしょうか。私はファイルの内容をハッシュすることに部分的です。これは最近ではかなり一般的で、うまく機能します。

9
Evan Carroll

当時、Microsoftは画像(および同様のblobデータ型)をデータベースに保存する機能を誇張していました。これはSQL Server 2000のクールな新機能であり(7.0ではなく2000だったと思います)、多くの人がこのワゴンに飛びつきました。

BLOBをデータベースに格納することには、長所と短所があります。

一方では、すべてのデータと関連する画像またはドキュメントを1か所に保存してアクセスできます。イメージ/ファイル/ドキュメントを提供しているのはSQLであるため、アプリケーションユーザーは特別なネットワーク権限を必要としません。

一方、格納するBLOBのサイズと数によっては、データベースが非常に大きくなる可能性があります。これは、バックアップ、ストレージ要件、時間に敏感なリカバリ操作などに影響します。

SQL Server 2008では、ファイルストリーミングが導入されました。データベースにはファイルへのポインタが含まれており、ファイルはデータベースではなくサーバー上に存在しますが、データベースをバックアップすると、ファイルもバックアップされます。

バックアップは非常に大きくなる可能性がありますが、孤立したファイル/ドキュメント/ブロブ/イメージで終わることはありません。

私の個人的な好みは、データベースにポインター/ネットワークの場所を保存させ、ファイルサーバーにファイルを処理させることでした。とにかく、ファイルサーバーはこのようなタスクに最適化されています。

7
datagod

私の投票はどちらにも当てはまりません。 Amazon S3やMicrosftのCDNなどのシステムにデータを保存し、そのURLをデータベースに保存します。

このようにして、処理するモンスターサイズのデータ​​ベースがなくても、データに常にアクセスできるという信頼性を得ることができます。

6
paullb

一部はアプリケーション/環境(人を含む)に依存しますが、私はblobに行きます。

すべてをデータベースに保持することは、ファイルデータのレプリケーションが機能することを意味します。 FSファイルを同期するには、別のメカニズムが必要です。

一部のアプリケーションでは、ファイルシステムを変更しないでください。たとえば、本番環境のWebサイトでは、使い捨てではないデータ(SCMの下にあるサイト、データベース内のデータ)にファイルシステムを使用することは避けます。

個別の権限を持つ複数のユーザー/アプリケーションがあると仮定すると、ファイルシステムストレージは、DBとFSアクセス権の違いをもたらす可能性を提供します。

私がBLOBストレージに対して行うことを検討する改良は、意味がある場合はデータをチャンク化することです。 20MbのBLOBから512バイトしか必要としない場合、特にリモートクライアントを処理している場合は、このセクターのようなアクセスが非常に役立ちます(また、部分的な更新によって複製トラフィックが大幅に減少します)。

6
Phil Lello

Postgresの場合:

それは実際には前向きです。バイナリ文字列の保存に使用できる BYTEA タイプがあります。デフォルトでは、MSやOracleで言及されているような組み込みユーティリティはありません。そのため、大量の大きなファイルを保存して取得するのは面倒な作業になる可能性があります。また、アプリケーション内でファイルを変換する必要があります(ByteStreamなどを使用して、特定のMS/Oracleファイル<->データベースソリューションでこれがどのように機能するかはわかりません)。 lo タイプもあります。これらのタイプの内部管理の一部は参照を追跡できない可能性があるため、BLOBの管理作業に役立ちます。

3
DrColossos