現在、ユーザーがファイルを保存および共有できる、1 MB〜10 MBのサイズのWebアプリケーションを作成しています。
ファイルをデータベースに保存すると、データベースアクセスが大幅に遅くなるように思えます。
これは有効な懸念事項ですか?ファイルをファイルシステムに保存し、ファイル名とパスをデータベースに保存する方が良いですか。データベースで作業する場合のファイルの保存に関連するベストプラクティスはありますか?
私はPHPおよびこのプロジェクトのMySQLで作業していますが、ほとんどの環境で同じ問題です( Ruby on Rails 、 [〜#〜] php [〜#〜] 、 。NET )およびデータベース(MySQL、 PostgreSQL )。
データベースにファイルを保存することを支持する理由:
データベースにファイルを保存する理由:
FILESTREAM
オブジェクトなどのシステム固有の機能を使用していて、別のデータベースシステムに移行する必要がある場合は、移植性が問題になることがあります。IMO、データベース内のファイルの保存を「悪い」と見なすには、状況と要件に関する詳細情報が必要です。ファイルのサイズや数は常に小さくなりますか?クラウドストレージを使用する予定はありませんか?ファイルはWebサイトまたはWindowsアプリケーションのようなバイナリ実行可能ファイルで提供されますか?
一般に、私の経験では、パスの保存は、ACIDの欠如と孤立の可能性を考慮に入れても、ビジネスにとって費用がかからないことがわかっています。ただし、これは、ACID制御の欠如がファイルストレージでうまくいかないという話がインターネットに影響を与えるわけではないことを意味しますが、一般に、ソリューションの構築、理解、維持がより簡単になることを意味します。
多くの場合、これは悪い考えです。データベースファイルが膨張し、いくつかのパフォーマンスの問題が発生します。列数が多いテーブルで blobs を使用すると、さらに悪くなります。
しかしながら! SQL Server などの一部のデータベースには、FILESTREAM列タイプがあります。この場合、データは実際にはデータベースサーバー上の別のファイルに保存され、ファイルへのIDのみがテーブルに保存されます。この場合、SQLサーバーにデータを保持しない理由の多くはわかりません。ファイルはサーバーバックアップの一部として自動的に含まれ、データベースとファイルが同期することはありません。ファイル名の保存に関するTonyの提案の問題は、データベースとファイルシステムが同期しなくなる可能性があることです。ディスク上でファイルが削除されると、データベースはファイルが存在すると主張します。プロセスがデータベースを変更していてクラッシュした場合、ファイルとデータベースは一致しません(つまり、データベース外のファイルとは [〜#〜] acid [〜#〜] になります)。
はい、それは悪い習慣です。
DBへのパフォーマンスの影響:
SELECT
を実行すると、常にディスクアクセスを実行しますが、BLOBを使用しないと、RAMから直接データを取得する機会があります高スループットDBは、RAMのテーブルに合うように最適化されます)。速度の利点— なし!古いファイルシステムの中には、何百万ものファイルを含むディレクトリを処理できないものもありますが、最近のほとんどのシステムではまったく問題がなく、実際にはBD(通常はBツリー)と同じ種類のデータ構造を使用しています。たとえば、ext4(デフォルトのLinuxファイルシステム)は Htree を使用します。
結論:DBのパフォーマンスが低下し、ファイルの取得パフォーマンスは向上しません。
また、ウェブアプリケーションについて話しているため、最新のウェブサーバーを使用してファイルシステムから静的ファイルを直接提供します sendfile()
syscall is tremendousパフォーマンスの向上。もちろん、DBからファイルをフェッチしている場合、これは不可能です。たとえば、 このベンチマーク を考えてみます。Ngnixはローエンドのラップトップで25Kリクエスト/秒で1000同時実行接続を示しています。この種の負荷は、あらゆる種類のDBを処理します。
私はそれについて実用的で、「まだ最適化しない」という原則に従います。現時点で意味のあるソリューションと、適切に実装するための開発リソースがあるソリューションを作成します。 潜在的な問題はたくさんあります。しかし、それらは必ずしも実際の問題になるわけではありません。例えば。 100人のユーザーがいる場合は、おそらく問題にはなりません。 100,000人または10,000,000人のユーザーがいる場合、mightが問題になることがあります。しかし、後者の場合、すべての問題に対処するための開発リソースを増やすための基盤が必要です。
ただし、データベースにデータを保存することで、他の問題(たとえば、ファイルを保存する場所、ファイルをバックアップする方法などシステムなので、プロセスがデータが格納されているフォルダへの読み取り/書き込みアクセス権を持つようにサーバーを構成する必要があります。
私は個人的にデータベースにデータを保存することを選択しますが、本当に必要になるまでBLOBが読み込まれないようにしてください。つまり、ブログを含むテーブルで「SELECT * FROM ...」が実行されないようにします。また、パフォーマンスの問題が発生した場合は、データベースからファイルシステムにデータを簡単に移動できるように設計されています。たとえば、ファイル情報を別のFileテーブルに格納し、ファイル情報を他のビジネスエンティティから遠ざけます。
データベースで読み取られたファイルを表すFileクラスがあると仮定すると、後でそれを移動することによるコーディングへの影響は最小限になります。
Microsoftは数年前にこれに関するホワイトペーパーをリリースしました。それはSqlServerに集中していますが、そこにいくつかの興味深い情報を見つけるかもしれません:
彼らの結論の非常に簡潔なバージョンは:
NTFSファイルシステムとSQL Server 2005を比較すると、256KB未満のBLOBはSQL Serverによってより効率的に処理されますが、NTFSは1MBを超えるBLOBSに対してより効率的です。
特定のユースケースに合わせていくつかの小さなテストを書くことをお勧めします。キャッシュ効果に注意する必要があることを覚えておいてください。 (物理的に可能なスループットよりもスループットが高いように思われるディスクへの保存速度を初めて取得したときは驚きました!)
データベースの外にファイルを保存するという従来の常識は、もはや成り立たないかもしれません。原則として、速度よりも整合性を優先します。最新のDBMSでは、両方を使用できます。
トム・カイトは 同意する のようです:
データベースの外で長期間保持したいデータを保存する利点がないことを知っています。
データベースにある場合は、
それが専門的に管理されていることを確認してください
バックアップした
回復可能(残りのデータと共に)
確保された
スケーラブル(100,000のドキュメントを1つのディレクトリに配置してみてください。今度は、それらをテーブルに配置します-これは「スケーリング」-ディレクトリではありません)
簡単に削除を取り消すことができます(フラッシュバック)
ロックがあります
読みの一貫性があります...
はい。
ファイルシステムからファイルを提供する場合、WebサーバーはBSDまたはLinuxのsendfile()などのカーネルコードを使用して、ファイルを直接ソケットにコピーできます。それは非常に高速で非常に効率的です。
データベースからファイルを提供するということは、データベースサーバーのディスクからデータベースサーバーのメモリにデータをコピーし、次にデータベースサーバーのメモリからデータベースサーバーのネットワークポートにコピーし、次にネットワークからWebサーバープロセスにコピーし、次に再び発信ネットワーク接続。
本当に正当な理由がない限り、ファイルシステムから静的ファイルを提供する方が常に良いでしょう。
有名なTom Kyteは、彼ら(Oracle)がOracleデータベースをファイルサーバーとして使用しており、完全に正常に動作し、通常のファイルシステムよりも高速で、完全なトランザクション性、パフォーマンスの損失なし、単一のバックアップで動作すると書いています。
はい。ただし、これらはOracle DBのプロデューサーであり、他のユーザーにとってはコストの問題があります。 Oracleのような商用DBをファイルの保存に使用することは、単にコスト効率が悪いだけです。
ただし、たとえばPostgreSQLでは、BLOBストレージに対してのみ別のDBインスタンスを実行できます。その後、完全なトランザクションサポートが提供されます。ただし、トランザクション性にはDBスペースがかかります。複数の同時トランザクションの複数のblobインスタンスをデータベースに格納する必要があります。 PostgreSQLでは、これが最も苦痛です。このデータベースには、トランザクション用に作成されたblobの複製が保存されます。VACUUMプロセスが完了するまで、不要になった場合でも、それらは保存されます。
一方、ファイルシステムストレージでは、トランザクションがロールバックされ、古いバージョンが表示されなくなるまでファイルのコピーを保持する必要があるため、誰かがファイルを変更するときは十分に注意する必要があります。
ファイルが追加および削除されるだけで、ファイルへのトランザクションアクセスが問題にならないシステムでは、ファイルシステムストレージが最良の選択です。
通常、大きなBLOBを別のテーブルに格納し、BLOBへの外部キー参照をメインテーブルに保持することをお勧めします。そうすれば、データベースからファイルを取得でき(特別なコードは不要)、外部DBの依存関係に関する問題(DBとファイルシステムの同期を保つなど)を回避できますが、そのオーバーヘッドのみが発生します。そのテーブルに明示的に参加する場合(または別の呼び出しを行う場合)。 10MBはそれほど大きくなく、ほとんどの最新の商用データベースには問題がありません。ファイルシステムにファイルを保存する唯一の理由は、データベースの帯域幅を削減することです。データベースでこれらのファイルの多くをシャッフルする場合は、ワークロードを分割して、ある種のファイル記述子のみを格納する必要がある場合があります。次に、別のサーバーからファイルをロードするための個別の呼び出しを行うことができます。これにより、データベース接続(およびデータベースサーバー上のネットワーク接続)をこれらすべてのファイル転送で拘束する必要がなくなります。
この問題のいくつかに遭遇するかもしれません:
SELECT *
ブロブが必要ない場合でも、大きなブロブを含む行を含むには非常に時間がかかります(もちろん、特定の選択を行う必要がありますが、アプリケーションは次のように記述される場合があります)もちろん、いくつかのメリットもあります。
個人的には、短所がプロよりもはるかに重いと思うので、私はそれをしません。しかし、上記のように、それは完全にあなたのユースケースなどに依存します。
SiteCoreなどの一部のエンタープライズコンテンツ管理システムは、1つのデータベースを使用してページデータを保存し、別のデータベースを使用してファイルを保存しています。彼らはMS SQL Serverを使用しています。
実用的な実装のために、ここにあなたが心配するかもしれないものがあります:
メリット:
欠点:
これは、「かみそりの刃を使ってリンゴを切り開くことはできますか」の1つです。はい、できます。
しますか? 誰に伝えるか ...
私は、ツールがそれを許可するか、または利用可能な唯一のツールである(少なくともその期限を達成するための)状況にいると思います。たとえば、マイナスドライバーを使用してフィリップスボルトタイプを取り外しました...それでよろしいですか?それは正しいツールでしたか?それは悪い選択でしたか?
この場合の答えは次のとおりです。DBはファイルを保存することを想定していません...間違っている場合はいつでも、理論的にはマイナスドライバを使用してフィリップスボルトを外すべきではありませんでした。フィリップススクリュードライバーの位置がずれず、私が作業しているものに損傷を与えないという利点(DBをファイルストレージソリューションとして使用すると、利点が失われるため)...でも、リスクを適切に計算したところ、すべてがうまくいきました。
正しいことをしたい場合は、おそらくgitを使用してファイルを格納し、必要なgitハッシュをDBに保持して、必要な正しいファイルバージョンを参照する必要があります...私のツールにアクセスするのと同じ方法でボックスとくそフィリップスドライバーを取得...