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


123

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

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

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

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

編集:

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


8
この質問はここに重複しています:画像をblobまたはURLのみに保存する方が良いでしょうか?この方がより優れているので、この方を支持して閉鎖されました。詳細については、両方の質問を必ずお読みください!
マリアン

回答:


57
  1. BLOBを使用してデータベースに保存する

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

  2. データベース内のリンクを使用してファイルシステムに保存する

    このような恐ろしい災害に遭遇したことがあり、人々がそれを提案し続けるのは怖いです。災害には次のものが含まれます。

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

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

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


2
バックアップサイズが問題かどうかわかりません。データはバックアップする必要がありますが、保存されています。FSについてもDBについても、同じ差分と完全な決定が行われます。これはあなたの視点ではなく、可能な議論であることに注意してください。
フィルレロ

2
私はかつて、1日に数千回、数百メガバイトが各行に書き込まれるという問題を抱えていました。彼らはGZIPファイルを10000サーバーのバイナリとしてDBに保存していましたが、すべてのサーバーがアラートごとにすべてのサーバーの情報を記録するバグが導入されました。ひどかった。その事件の後、私は「極端に正当化されない限り、(MAX)データ型がない」ことに固執しました。
アリラゼギ

7
「リンクの破壊」全体はアプリケーションの問題であり、データベースの問題ではありません。データベースはその仕事をしています(純粋なデータを提供しています)が、アプリケーションはそうではありません(混合ファイルタイプを提供しています)。アプリケーションには、ファイルを提供する責任があります。ファイルがサーバーのどこに内部的に保存されていても機能する抽象ルートパスをデータベースに保存することにより(ala Symfony2ルーティング)。これにより、ネイティブパスが抽象化され、アプリケーションの移植性と保守性が向上し、何も壊さずにあらゆる種類のファイルシステムに切り替えることができます。
Tekの

29

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

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


(3)具体的には、データの整合性を危険にさらすものは何ですか?(トランザクションAPIが正しいと仮定)
ジャックダグラス

4
@JackPDouglas:正しいデータではないハッシュがあり、まだデータ整合性の外部依存関係があります
-gbn

6
@JackPDouglasまた、サーバー管理者とDBAが異なるチームである可能性もあり、ファイルが誤って削除されたり、一時ファイルと考えられているためバックアップされなかったりするリスクがあります。
フィルレロ

21

Oracleを使用する場合は、dbfsとSecure Filesをご覧ください。

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

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

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

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

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

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


15

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

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

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

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

中規模ビジネスの場合、チケットシステムのドキュメントをインラインで保存すると、メガバイト単位で測定された圧縮バックアップとギガバイト単位で測定されたバックアップの差が生じる可能性があります。

個人的には、チケットシステムを数分でオンラインに戻し、数時間(一般的にはそれほど重要ではない)文書と格闘することを好みます。さらに大きなバックアップからログを再生します。

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

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

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

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


11

しないでください。

データベースにファイルを保存することの利点はありません。

あなたが自分で考えるとき、それはすでに奇妙で怪しい感じがしませんか:

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

さらに良いことに、大声でそれを言う。

事実について:

データベースを使用する

長所」... しかし完全ではない

  • 「原子性」は正しいですが、それは両刃の剣です。それはそれと一緒に短所をドラッグするため。
  • 整合性。同上。

私は本当に偏見を持ちたくありませんが、追加するものがあるとは思いません。あなたがそれについて考えるならば、プロは本当にそれほど素晴らしいものではありません。

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

短所:

  • 仕事のための間違ったツール
  • メンテナンスが難しい
  • スロー
  • ユーザーごとに数百MB /ギガバイトのデータを保存することを忘れてください。
  • 急速に成長しているサイトのバックアップは悪夢です。
  • 復元/移動もお粗末です。

ファイルシステムを使用する

長所:

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

短所

  • 無し*

*ファインプリント

今、あなたは自分自身に問いかけています、あなたは短所がないことを意味しますか?どうして?

ここでの最大の間違いは、人々がハンマーでネジを締めようとしていることです。

主な理由と私はこれが尋ねられている唯一の理由はファイルリンクのためであると言ってまで行きます

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

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

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

解決策:

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

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

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

https://github.com/symfony/Routing

https://github.com/kriswallsmith/assetic

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


1
これに興味があるかもしれません:research.microsoft.com/apps/pubs/default.aspx? id=64525データベースへのBLOBの保存は実際にはファイルシステムよりも速いことを示すMicrosoftの調査(BLOBのサイズによっては)少なくとも)。これは、中規模のブロブ(<〜1MB)の場合、たとえばPostgresがファイルシステムよりも高速であることを示した私のテストと一致しています。Oracleの場合、パフォーマンスはほぼ同じですが、新しいsecurefileストレージ形式はまだテストしていません(ただし、古いストレージ形式よりも高速であると主張しています)
a_horse_with_no_name 14

それを見たので、大きなファイルについて話しました。さらに、OPはデータベースベンダーを指定しなかったため、ベンダー間でパフォーマンスが異なる場合があるため、私のアドバイスはより一般的です。
Tek 14

9

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

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

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

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


7

昔、マイクロソフトはデータベースに画像(および同様のblobデータ型)を保存する機能を誇示していました。これはSQL Server 2000のクールな新機能であり(7.0ではなく2000であったと確信しています)、多くの人々がこの時流に飛びつきました。

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

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

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

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

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

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


5
サーバーを所有していない場合は、データベーススペースとファイルスペースに対して、MBあたりかなり多く支払うことになります。また、ディスク上にファイルがあると、トラブルシューティングがはるかに簡単になりますSELECT image FROM table。SSMSでどのように適切なイメージが存在することを確認しますか?
アーロンバートランド

7

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

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

  • データベース内のファイルへのfilehandesはありません。これは何を意味するのでしょうか?

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

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

  • RDBMSで二重コピーします。それがデータベースにあるという事実によって、あなたはおそらくそれを二度書くでしょう。先行書き込みログ(WAL)に入れてから、再びテーブルスペースに入れます。

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

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

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

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

  • コピーオンライトまたは重複除外なし XFSおよびBTRFSは、コピーオンライトおよび重複除外を透過的にサポートします。これは、どこでも同じ画像を持っているか、その画像の2番目のコピーが必要であることを、ファイルシステムが透過的に処理できることを意味します。ただし、ファイルが単独で存在せず、行上またはストア内にある場合、ファイルシステムは重複排除できません。

  • 整合性は、多くの人々がここに整合性について話しているされています。ファイルシステムの破損、ファイルシステムまたはファイルシステムのコアユーティリティを使用するアプリケーションを検出する上で、何がより良いと思いますか?ファイルを行に格納するか、行外にすると、ファイルシステムの破損がデータベースを覆い隠します。xfs_repairファイルシステムまたはハードドライブの破損が発生した場合の復旧は非常に優れており、失敗した場合でもデータフォレンジックを行うのはずっと簡単です。

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

例外

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

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

緩和策

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

  • データベースの中には、Oracle SecureFileのように、大規模なバイナリ・オブジェクトを表外または缶に格納するものがあります。これにより、ファイルを書き換えずに行を更新できます。

  • Oracleなどの一部のデータベースは、WALログなしでMVCを実行するため、ファイルを2倍に書き込む必要はありません。

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

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

結論

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

シンプルに保ち、一般的なルールはファイルをDBに入れないことです

解決

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


6

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

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

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

個別のアクセス許可を持つ複数のユーザー/アプリケーションがあると仮定すると、ファイルシステムストレージはDBとFSのアクセス権が異なる機会を提供します。

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


6

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

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


3

postgresの場合:

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


-4

Ms SQLサーバーの経験と膨大な数のファイルを共有してください。ファイルサーバーにファイルを保存します。データベースには2つのテーブルがあり、1つはファイルフォルダー用で、もう1つはファイル名用です。データベースとファイルの管理は簡単です。フォルダーテーブルを変更するだけで、サーバー間でファイルを簡単に移動できます。

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