質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
NoSQL

NoSQL(not only SQL)は、リレーショナルデータベース管理システムとは異なるデータベースシステムを指す言葉です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

4516閲覧

LevelDBについて教えて下さい!

nao_otsu

総合スコア18

NoSQL

NoSQL(not only SQL)は、リレーショナルデータベース管理システムとは異なるデータベースシステムを指す言葉です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2016/02/05 14:12

億を超える膨大な数の画像(小さすぎもなく大きくもないサイズ)のバイナリデータを保存する場合
LevelDBのようなKey-Value型のDBを利用は適しているのでしょうか?
また保存するバイナリデータが動画のように大きくなった場合でもLevelDBの利用は向いているのか教えて下さい。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
tatsuya6502

総合スコア2035

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nao_otsu

2016/02/06 03:48

tatsuya6502さん 丁寧に教えて頂きありがとうございます。 どんなサイズのデータでも格納できると思ってたのですが、LevelDBにあったデータサイズのデータの格納を心がけた設計を考えようと思います。 LevelDBについて曖昧な理解しかしてなかったため、キャッシュなしでも早い理由がなんとなくですが分かった気がします!もっと調べて理解しようと思います。 いろいろと参考にさせていただきます。
nao_otsu

2016/02/06 12:45

質問よろしいでしょうか? 本文で LSMT(Log-Structured Merge-Tree)というデーター構造を使っているので、索引をメモリーにキャッシュしなくても性能をキープできることが強みになっています。 とありますが、キャッシュをしなくてもキャッシュを利用した時と同等の速度は出るのでしょうか? わかる範囲で教えていただけると助かります。
tatsuya6502

2016/02/06 14:24

ああ、何の性能なのか書いてなかったですね、ごめんなさい。 これは書き込み性能のことを言っていました。データーの書き込み(追加、更新、削除)を行うとき、B-Tree索引を使った RDBMS では、索引も更新するのです。そのためには、まず、索引の中で必要な部分をディスクから読み込み、続いて、上書き更新をかけないといけません。索引の大半がキャッシュに載っている間はいいのですが、データー量が膨大になって索引も巨大になると、索引がキャッシュに載りきらなくなります。そのため、索引の読み込みに待ち時間が生じ、結果として、データーの書き込み性能が大きく劣化します。 一方、LSM Treeの方は、データーの書き込み時に何かをディスクから読み込む必要はありません。データーファイルの SSTable 自体が索引として働くようになっており、しかも、Log-Structured(ログ構造)と呼ばれる通り、この SSTable は追記のみで、一度書かれた内容は上書きされません。また、クライアントのからのデーター書き込み要求は、コミットログと、MemTable に記録されるだけです。SSTable の書き込みはその後、MemTableが一杯になった時に、バックグラウンドで行われるようになっています。 このような仕組みなので、データー量が膨大になっても、書き込み性能が劣化しません。 なお、LSM Tree は、読み込みの性能はそこそこというレベルで、決して速くはありません。これは、Merge-Tree の名の通り、読み込み時は複数世代ある SSTable から読みだした内容を、メモリー上でマージしなければならないからです。ただこれも、データー量が膨大になっても、性能が劣化しないという特徴があります。 もちろん、読み込み時は、SSTable の内容がメモリーにキャッシュされていると、性能が上がります。LevelDB では、DB を open する際にキャッシュサイズを指定できます。
nao_otsu

2016/02/07 06:32

読み込みの際はSSTableの内容がキャッシュできなくなってしまっても、読み込み速度は少し落ちてしまうけれど、読み込み性能が大きく劣化することはないということですね。 詳しく教えていただき感謝です。また、質問するかもしれませんがよろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問