億を超える膨大な数の画像(小さすぎもなく大きくもないサイズ)のバイナリデータを保存する場合
LevelDBのようなKey-Value型のDBを利用は適しているのでしょうか?
また保存するバイナリデータが動画のように大きくなった場合でもLevelDBの利用は向いているのか教えて下さい。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
私は仕事で分散型オブジェクトストア製品の開発に携わっています(Amazon S3 のようなことをするサーバー製品です)。また、プライベートの時間では、画像などの大きめのデータにも対応できる、分散型 NoSQL の開発もしています。なのでこの分野は専門なのですが、
LevelDB は格納できるキーバリューのサイズに制限を設けていないので、画像データ(数百KBから数MB)を格納することは物理的には可能です。が、その用途に向いているかというと、そうではありません。
理由は、LevelDB では、キーバリューをディスクに格納する際、数百から数十万というキーバリューを1つのファイル(SSTable と言います)にまとめないことには、性能を発揮できないからです。SSTable の中では、キーバリューをキー順でソートしておかなければならないのですが、LevelDB はそのソートをメモリー上で行います(キーバリューを MemTable というメモリー上のデーター構造にいったん蓄えます)。メモリーをあまり圧迫しないように、LevelDB は MemTable のサイズをできるだけ小さく保とうとします。すると、1つの SSTable に格納できる画像の数も減ってしまい、結局、画像を直接ファイルシステムに格納するのと、大差なくなってしまいます。
また、Level DB にはコンパクションという処理があります。これは、SSTable に格納されたキーバリューの中で、いまでも有効なものだけを、新しい SSTable へコピーするという処理です。画像のような大きなデーターを何度もコピーするのは、あまり効率がいいとはいえません。
LevelDB が適しているのは、数KBくらいまでのキーバーリューを無数に格納することです。このようなデーターを数億件格納するくらいなら、MariaDB などでも楽々処理できるはずなので、違いはわからないかもしれません。しかし、これらの DB は、キーの索引に B-Tree インデックスというものを使っているので、この索引がいったんメモリーにキャッシュできなくなると、性能がガタ落ちします。LevelDB は索引として LSMT(Log-Structured Merge-Tree)というデーター構造を使っているので、索引をメモリーにキャッシュしなくても性能をキープできることが強みになっています。
なお、LevelDB に動画のような巨大なデーターを直接格納するのは無理です。なぜなら、API として、メモリー上にあるキーバリューを、まるごと put、または、get することしかできないからです。数GBあるデーターをアプリ側でメモリーに読み込んでから、DB に格納するのは非効率ですよね。また、動画の場合はデーターの途中から少しずつ読みだすといった操作も必要ですが、LevelDB では、このような操作はできません。
本当は C++ から呼びだせて、こういう目的に適した専用のデーターストアがあればいいのですが、ちょっと思い当たりません。
大きなデーターを Level DB などに格納するためによく使われる手法の一つに、チャンキングがあります。これは、そのまま格納するには大きすぎるデーターを、アプリ側で適当な大きさ(数KBくらい)に分割してから格納する方法です。以前、仕事で LevelDB を使って、QEMU(仮想マシン)の実験的なストレージドライバを開発したことがあるのですが、そのときは、まあ普通に使えるくらいには動いていました。ちなみに、その時、チャンキングのサイズは、ゲスト OS として使われる Linux のファイルシステムのブロックサイズに合わせて 4KB にしました。よく数MBでチャンキングしてるのを見かけるのですが、これだとあまり性能が出ないと思います。
もうひとつのよくある方法は、LevelDB はメタ情報(画像データのファイル名、作成者、アクセス権などの情報)だけの格納に使って、画像の本体は、ファイルシステムにファイルとして格納することです。ファイル数がよほど多くならない限りは、この方法のほうが、チャンキングよりも性能が出ます。ただ、ファイルシステムでは、1つのディレクトリーに数万というファイルを入れると全体的な動きが鈍くなるので、適当にディレクトリーを分けてあげる必要があります。これは、例えば、親のディレクトリーの名前に、キーのハッシュ値の一部を使うといった方法で実現できます。あと、ファイルシステムも、inodeというファイルやディレクトリーを管理するためのデーター構造に B-Tree インデックスを使っているので、格納したファイルの数があまりにも大きくなると、性能が大きく落ちます。
どちらを選ぶかは、うーん、データー件数に依存するのですが、数億件程度でしたら、後者のほうが作るのも簡単で、性能も出るのでいいと思います。ただ、ハードドライブの容量はいまでも大きくなり続けていますし、サーバーだとハードドライブを30台以上搭載することもできますので、もし、そういうレベルの件数を想定しているなら、簡単なアプリを試作して、実際にテストしてみることをおすすめします。
投稿2016/02/06 00:02
編集2016/02/06 00:53総合スコア2035
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/02/06 03:48
2016/02/06 12:45
2016/02/06 14:24
2016/02/07 06:32