【问题标题】:Large memory usage for sqlite3sqlite3 占用大量内存
【发布时间】:2017-04-01 16:18:45
【问题描述】:

我一直在我的 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

【问题讨论】:

    标签: python python-2.7 memory sqlite


    【解决方案1】:

    SQLite 按需计算结果行。但是当您使用 ORDER BY 时,数据库必须对所有行进行排序并将该临时列表保存在内存中。

    为了避免排序,您必须在数据库中保留一个排序列表,即在 slice 列上创建索引。 (重要的是,不仅行实际上已排序,而且查询优化器能够证明它们已排序。)

    【讨论】:

    • 整洁!因为我不要求索引是唯一的,所以这是完美的
    猜你喜欢
    • 2014-05-11
    • 2011-02-27
    • 2013-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多