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