私は非常に大きなデータベースを持っています - 私は 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 の結果を返します。
このクエリの最適化に関する提案はありますか?