5

私は非常に大きなデータベースを持っています - 私は 3 億 5000 万行のサブセットで作業していますが、最終的には約 30 億行になります。ここでの私の全体的な目標は、メモリ以外のほとんどすべてを犠牲にして、このデータベースで特定のタイプのクエリを最適化することです。私が現在取り組んでいる db ファイルは、PyTables バージョン 2.3.1 でレベル 1 の blosc で圧縮されています (それが役立つ場合は更新できます)。各行には 13 のエントリがあります。典型的なエントリは次のようになります。

['179', '0', '1', '51865852', '51908076', '42224', '22', '2', '20', '22', '2', '0.0516910530103', '0.0511359922511']

それらはすべて数値ですが、必ずしも同じ型ではありません。私は現在、次の定義でそれらを PyTables テーブルに格納しています。

ind = tables.UInt16Col(pos=0)
hap = tables.UInt8Col(pos=1)
chrom = tables.UInt8Col(pos=2)
hap_start = tables.Int32Col(pos=3)
hap_end = tables.Int32Col(pos=4)
hap_len = tables.Int16Col(pos=5)
mh_sites = tables.Int16Col(pos=6)
mh_alt = tables.Int16Col(pos=7)
mh_n_ref = tables.Int16Col(pos=8)
all_sites = tables.Int16Col(pos=9)
all_alt = tables.Int16Col(pos=10)
freq = tables.Float32Col(pos=11)
std_dev = tables.Float32Col(pos=12)

このデータベースをセットアップするのにどれくらいの時間がかかるかはあまり気にしません。最終的にはデータベースを一度作成してからアクセスするだけです。私のクエリは次の形式です。

a = [ x[:] for x in hap_table.where('''(mh_sites == 15) & (hap_len > 25000) & (hap_len < 30000) & (freq > .38) & (freq < .4) & (std_dev > .3) & (std_dev < .4)''')]

基本的に、特定の許容範囲の特定の行に一致するエントリを検索しています。私の小さなデータベース (3 億 5000 万行) では、検索対象の 4 つの列すべてにインデックスを付けた場合、そのクエリには 38 秒かかります。

byteorder := 'little'
chunkshape := (32768,)
autoIndex := True
colindexes := {
  "hap_len": Index(6, medium, shuffle, zlib(1)).is_CSI=False,
  "freq": Index(6, medium, shuffle, zlib(1)).is_CSI=False,
  "std_dev": Index(6, medium, shuffle, zlib(1)).is_CSI=False,
  "mh_sites": Index(6, medium, shuffle, zlib(1)).is_CSI=False}

事前にインデックスを作成しない場合は 10 秒です。インデックス化されたデータベースでクエリが遅くなる理由を理解しているかどうかはわかりません..インデックス作成により不要なオーバーヘッドが発生する可能性がありますか?

私が言ったように、私の目標は、このタイプのクエリを可能な限り最適化することです-基本的にメモリ使用量以外のすべてを犠牲にします(私は約2Gを使用したいのですが、実際には約5G以上を使用したくありません)。インデックスを作成しようとしましたが、うまくいかないようです。私のクエリはすべて mh_sites の単一の値であり、可能な値は約 100 しかないため、複数のテーブルに分割することを考えたので、一度にデータのサブセットのみを検索しています (ただし、 mydata.root.table_1、mydata.root.table_2 などを除いて、それを行う方法が完全にはわかりません)。また、代わりに配列として保存しようと考えました-おそらく浮動小数点配列であり、それらを使用する必要があるときに他のすべてをintに変換しますか? それが違いを生む場合、私のクエリは通常 20k から 500k の結果を返します。

このクエリの最適化に関する提案はありますか?

4

1 に答える 1

5

これをもっと速くする方法を見つけました - そして私の解決策は他の人を助けるかもしれないので、ここに投稿しています.

PyTables でのインデックス作成の仕組みについて混乱していました。CSI は実際にデータをソートすると考えましたが、そうではありません。一連の行を追加すると、それらは常にその順序になります。私にとっては、データを挿入する前にデータをソートすることは、オーバーヘッドに見合った価値がありました。クエリ時間が 1 ~ 2 桁短縮されました。

これは、テーブルのインデックス作成によって実際にクエリ時間が増加した理由も説明しています。行は基本的にランダムに分散されていたため、クエリごとにデータベース全体を読み取る必要がありました。したがって、とにかくすべてのブロックを読み取る必要があるため、pytables がインデックスを使用してどのブロックを読み取る必要があるかを判断できるかどうかは問題ではありませんでした。そのため、データがソートされていない場合、インデックスによってオーバーヘッドが追加されました。ソートされたテーブルでは、インデックスが確実に役に立ちます。

于 2013-08-08T16:43:43.197 に答える