2013-07-25 17 views
5

私は非常に大きなデータベースを持っています - 私は350m行のサブセットで作業していますが、最終的に約3b行になります。私のここでの目標は、このデータベースの特定のタイプのクエリを最適化することです。ただし、メモリ以外のほとんどすべてを犠牲にしています。私が今作業しているdbファイルは、PyTablesバージョン2.3.1でレベル1のbloscで圧縮されています。各行は13個のエントリを持っている - 一般的なエントリは次のようになります。pytablesで複雑なtable.where()クエリを最適化しますか?

['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)''')] 

基本的には、特定の許容値を超える特定の行に一致するエントリを検索しています。私は事前にインデックスをいない場合

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秒:私は上の検索だ4つのすべての列をインデックス化した場合、私の小さなデータベース(350メートル行)で、そのクエリは38秒かかります。私は、なぜクエリがインデックスデータベースの速度が遅いのかわかりません。おそらくインデックス作成では必要ないオーバーヘッドが発生するでしょうか?

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

このクエリの最適化についてのご意見はありますか?

答えて

5

これをもっと速くする方法を見つけました。私の解決策は他の人に役立つかもしれないので、私はここに掲載しています。

PyTablesでのインデックス作成の仕組みが混乱していました。私は、CSIが実際にデータを並べ替えると考えていましたが、そうではありません。の行を追加すると、常にその順番になります。私にとっては、データを挿入する前にデータを並べ替えるのはかなりオーバーヘッドに値するものでした。私の照会時間は1〜2桁減少しました。

これはまた、テーブルをインデックス化すると実際にクエリ時間が長くなった理由も説明しています。つまり、行が基本的にランダムに分散していたためです。とにかくすべてのブロックを読む必要があったので、どのブロックを読み込む必要があるかをpytablesが索引を使って調べることができるかどうかは関係ありませんでした。したがって、データはソートされていないときにインデックスにオーバーヘッドが追加されました。ソートされたテーブルでは、インデックスが確実に役立ちます。

+1

データセットがあまりにも大きくソートされた場合は、追加する前に必ずソートする必要はありません。その場合、CSI索引を作成し、次にsortbyキーワードを使用して表をコピーします。このキーワードは、メモリー内に完全なデータセットを持つことなく、正しい順序で行を配置します。ソートされた方法でセットをコピーするには時間がかかるため、時間が問題になる可能性があります。しかし、あなたが一度書くと頻繁にクエリを行うシナリオでは、面倒なことに価値があるかもしれません。 –

+0

これはPyTablesのドキュメントでも言及されています:[最適化 - 究極の速度を達成する:ソートされたテーブルとそれ以降](http://www.pytables.org/usersguide/optimization.html#achieving-ultimate-speed-sorted-tables-and) -超えて) – 153957

関連する問題