2017-04-01 351 views
0

私はPython2プロジェクトでsqlite3を使用していますが、小さなメモリフットプリントを残しながら作業を高速化しています。しかし、データベースクエリでORDER BY句を使用すると、多くのRAMメモリが消費されるという不思議な問題が発生しました。私は本当に原因とこの問題を回避する方法についてはよく分かりません。私はpython docsのsqlite3には何も見つかりませんでした。例を次に示します。sqlite3のメモリ使用量が大きい

私は簡単なテーブルを作成し、

import sqlite3 
from memory_profiler import memory_usage 

con = sqlite3.connect("order_mem.db") 
cur = con.cursor() 

cur.execute("CREATE TABLE ordertest (idx INT, slice INT, seq TEXT)") 

def load_data(): 

    for i in range(20): 
     for p in xrange(50000): 
      cur.execute("INSERT INTO ordertest VALUES (?, ?, ?)", 
         (p, i, "A" * 1000)) 

いくつかのダミーデータを挿入することができ、私は正常または注文したクエリを使用してデータを取得したい場合は、私は乱暴に異なるメモリ使用状況を取得します。順不同

def iterate_unordered(): 

    for i in cur.execute("SELECT idx, seq FROM ordertest"): 
     pass 

load_data() 
mem_usage = memory_usage(iterate_unordered) 
print(max(mem_usage)) 
# 33.99609375 

順序:

def iterate_ordered(): 

    for i in cur.execute("SELECT idx, seq FROM ordertest ORDER BY slice"): 

     pass 

load_data() 
mem_usage = memory_usage(iterate_ordered) 
print(max(mem_usage)) 
# 1028.78515625 

これはそんなにメモリをつかんせずにクエリを命じ実行する方法はありますか?

EDIT:CLごとに。列にソートされるインデックスを作成すると、その列のソート中にRAM消費量が大幅に削減されます。比較のために、インデックスの結果は次のとおりです。

cur.execute("CREATE TABLE ordertest (idx INT, slice INT, seq TEXT)") 
cur.execute("CREATE INDEX test ON ordertest(slice)") 

def iterate_ordered(): 

    for i in cur.execute("SELECT idx, slice, seq FROM ordertest ORDER BY slice"): 
     pass 

load_data() 

mem_usage = memory_usage(iterate_ordered) 
print(max(mem_usage)) 
#33.9296875 

答えて

1

SQLiteは必要に応じて結果行を計算します。しかし、ORDER BYを使用する場合、データベースはすべての行をソートし、その一時的なリストをメモリー内に保持する必要があります。

並べ替えを避けるには、データベースに並べ替えられたリストを保持する、つまりslice列にインデックスを作成する必要があります。 (行が実際にソートされるだけでなく、問合せオプティマイザがソートされていることを証明できることも重要です)

+0

Neat!インデックスは一意である必要はないので、これは完璧です – ODiogoSilva

関連する問題