我一直在我的python2项目中使用sqlite3来加速某些任务,同时留下很小的内存空间。但是,我偶然发现了一个奇怪的问题,即在数据库查询中使用ORDER BY
子句会消耗大量的RAM内存。我真的不确定原因以及如何规避这个问题。我在sqlite3的python docs中找不到任何内容。下面是一个例子。
我可以创建一个简单的表并插入一些虚拟数据
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
答案 0 :(得分:1)
SQLite按需计算结果行。但是当您使用ORDER BY时,数据库必须对所有行进行排序并将该临时列表保留在内存中。
为了避免排序,您必须在数据库中保留一个排序列表,即在slice
列上创建索引。 (重要的不仅是行实际排序,而且查询优化器能够证明它们已经排序。)