2017-04-01 60 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 

有沒有執行此命令查詢沒有抓住這麼多內存的方法嗎?

編輯:根據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

整潔!由於我不需要索引是唯一的,所以這是完美的 – ODiogoSilva