これは以前に尋ねられた質問です( large-text-and-images-in-sql )が、主に変更されるデータについてです。私の場合、データは保存され、変更されることはありません。すべてをまとめておくのが賢明なようです。
静的バイナリデータをデータベースに保存しない理由はありますか?
それを行うのが賢明であると仮定すると、そのようなデータを別々のテーブルに格納することには何か利点がありますか? (私がDBの専門家ではないことに気づくかもしれません...)
明確化:おそらく10〜20人のユーザーしかいないでしょうが、これらは米国と英国に存在します。いずれの場合も、バイナリデータを転送する必要があります。
データをDBに保存することの利点は、DBのセキュリティメカニズムを利用し、保守コスト(バックアップなど)を削減することです。この方法の欠点は、DBの負荷が増加し、接続が消費されることです(これは、接続ごとにライセンスが付与されたデータベースサーバーでは高額になる場合があります)。 SQL Server 2008を使用している場合、 FILESTREAM
が良い代替手段になる可能性があります。
ちなみに、Webアプリ(またはデータのストリーミングを必要とする可能性のあるその他のアプリ)の場合、通常、DBの外部にデータを保存する方が賢明です。
「select * from table」を実行することに関するこのすべての話は、テーブルにLOBが含まれている場合にメモリや帯域幅の巨大な問題を引き起こすことは問題ではありません。返されるのは、問題のLOBへのポインターだけです。コメントを前後関係に置くほどの評判はありませんが、これを見ている人は問題ではないことを知っているはずです。
BLOBを格納する場合の最大の欠点は、メモリの消費です。 select * from xが、それぞれに45kの画像がある何千ものレコードに対して何をするか想像できますか?
Mehrdadが言ったように利点もあります。したがって、そのアプローチを採用する場合は、ほとんどのクエリがBLOBデータを含む結果を返さないようにデータベースを設計する必要があります。たとえば、この目的のために1対1の関係を作成します。
原則の観点からこの問題に対処するため、構造化データを格納するためのリレーショナルデータベースが(主に)存在します。クエリ条件を作成したり、データ要素を結合したりできない場合は、おそらくデータベースに属していません。画像BLOBがWHERE句で使用されていないので、データベースの外に置いておきます。一方、CLOBはクエリで使用できます。
私はMySQLデータベースにイメージを保存することを最初に決定したかなり良いサイズのOSSプロジェクトに精通しており、それはそれ以来彼らが対処してきたトップ3の悪いアイデアの1つであることが証明されています。 (「容赦なくリファクタリングする」は嫌悪感であるという事実によって悪化しますが、それは別の話です。)
これが引き起こした深刻な問題の中で:
最大効率データベースサイズ(mysql)を超えています。 (画像に必要な総スペースは、他のすべてのスペースを少なくとも2桁超えています)。
画像ファイルは「ファイルネス」を失います。日付(管理用のコードが必要)として(冗長に)格納されない限り、日付のサイズなどはありません。
任意のバイトシーケンスは、ストレージまたは操作のいずれにおいても、常に適切に処理されるわけではありません。
「外部から画像にアクセスする必要はありません」は危険な仮定です。
もろさ。全体の配置は不自然で扱いにくいため、次にどこに噛みつくかはわかりません(アンチリファクタリングの考え方に貢献しています)。
メリット?それが当時最も抵抗の少ない道であったかもしれないことを除いて、私が考えることはできません。
これはあなたの建物のアプリケーションに依存すると思います。 CMSシステムを構築していて、データの使用がWebブラウザー内に画像を表示することである場合、データベースに保存するのではなく、画像をディスクに保存することは理にかなっています。正直なところ、両方を実行しましたが、ファイルをあちこちにコピーする必要なく、サーバーをファームに追加できました。
別のユースケースは、ワークフローなどの複雑なオブジェクト、または相互依存が多数あるビジネスオブジェクトです。これらの両方をバイナリまたはテキストベースの形式にシリアル化し、DBに保存できます。次に、DBのメリットを利用できます:ATOMIC、バックアップなど...
そもそもselect *
クエリを使うべきではないと思います。データを取得する方法は2つあります。1つは要約情報を返し、2つ目はblobを返します。何千もの画像を一度に返さなければならない理由がわからない。
画像(または他のバイナリドキュメント)をデータベースに格納するという考えを持っていた人は、私がとても満足している人ではありません。データベースは、[ほぼ?] INDEXABLE、DISCRETEデータの格納用です。意味のないバイナリデータのBLOBではありません。バイナリデータのBLOBを直接操作したことがある場合は、すでにご存じでしょう。
ファイルへの参照をファイルシステムに保存する必要があります。そのベストプラクティスは、絶対(または相対)パスではなく、ファイル名です。
添付ファイルはシステムに保存されており、添付ファイルを変更することはできないため、「保存され、変更されない」データと同じページにいると思います。具体的には、データベースに保存することをnotと決定しました。これは、2つの理由、シンプルさ、およびバックアップ/リカバリ時間のために行われました。
シンプルさを第一に:私たちの場合、これらの添付ファイルはエンドユーザーのブラウザからアップロードされ、SQLパイプにストリームするよりも(DBサーバー上の)ディレクトリに書き込むだけの方が簡単です。 DBにはそれらのレコードがありますが、DBには添付ファイルに関するメタ情報とディスク上のファイルの名前(この場合はGUID)のみが含まれています。
バックアップ/リカバリ側:これらのblobは、おそらくデータベースの最大の断片の1つになります。完全バックアップを実行すると、変更できないことがわかっている場合でも、これらのビットが何度もコピーされます。私たちにとっては、(はるかに)小さなバックアップを作成し、アタッチメントディレクトリをセカンダリサーバーにバックアップとしてxcopyするほうがはるかに簡単に思えました。
これは、LOBまたはCLOBまたは....が設計されたものではありませんか?
CLOBを使用して、主要な航空会社システムのクレジットカードカードトランザクションの大規模な暗号化を保存しました。
ただし、メモリ消費は最大の原因です。
HTH
乾杯、
一部のデータベース(Postgresqlなど)はフィールドを自動的に圧縮します。おそらく、フィールドをdbから直接読み取る方が高速です。また、プログラムはすべてのフィールドと画像を一度に読み取ることができます。
上記のパフォーマンス問題はここで取り上げたので、繰り返しはしません。しかし、大量にストリーミングされるもの(Webサイト上の画像/ドキュメントなど)を格納する場合の良いヒントは、キャッシュシステムを構築することです。
これはつまり、すべてのデータをデータベースに保存することを意味しますが、誰かがそのファイルを要求したときに、そのファイルがディスクに存在するかどうかを確認します(既知のファイル名に基づいて、一時フォルダーにあります)。存在しない場合は、DBからデータを取得して書き込みますフォルダを作成し、それをユーザーにストリーミングします。同じファイルへの次のリクエストでは、ディスク上に存在するため、DBにアクセスすることなく、そこからサービスを提供できます。しかし、これらのファイルを削除する必要がある場合(またはWebサーバーがkapputに移行する場合)は、ユーザーの要求に応じてDBから再構築されるため、問題ではありません。これは、DBからの同じファイルに対する各リクエストを処理するよりもはるかに高速です。