控制数据库查询流的更好方法

时间:2013-02-12 17:11:33

标签: python loops peewee

在我的程序中,我需要读取一个非常大的表(它超过了内存存储)并自己编写以下构造来从表中读取并完成一些工作。虽然我知道将select重写为迭代器样式是非常可能的,但它仍然具有以下基本结构:

    found = True
    start = 0
    batch = 2500
    while found:
        found = False
        for obj in Channel.select().limit(batch).offset(start):
            found = True

            # do some big work...

        start += batch

我想要做的是有些东西不会携带那些笨重的状态变量。关于如何清理这些混乱的想法?

仅供参考 - 我也试过这个,不确定我是否更喜欢它:

@staticmethod
def qiter(q, start=0, batch=25000):
    obj = True
    while obj:
        for obj in q.limit(batch).offset(start):
            yield obj
        start += batch

2 个答案:

答案 0 :(得分:1)

我找到的最短的内容如下:

for start in itertools.count(0, 2500):
    objs = Channel.select().limit(2500).offset(start)
    if not objs:
        break
    for obj in objs:
        # do some big work...

基本上它是两件事的组合:

  • count迭代器(来自标准库的itertools包)将批量计数减少到最小,并且
  • 使用单独的测试和break语句来摆脱它。

详细说明:

count迭代器非常简单:它产生无限系列0,2500,5000,7500,....由于这个循环永远不会结束,我们需要在某个地方break。这就是if语句发挥作用的地方。如果objs是空列表,则break存在外部循环。

答案 1 :(得分:0)

如果您只是迭代并且不想用完所有RAM,那么可以在QueryResultWrapper上查看“iterator()”方法。

例如,假设您需要迭代超过1,000,000行数据并将其序列化:

# let's assume we've got 1M stat objects to dump to csv
stats_qr = Stat.select().execute()

# our imaginary serializer class
serializer = CSVSerializer()

# loop over all the stats and serialize
for stat in stats_qr.iterator():
    serializer.serialize_object(stat)

以下是文档的链接:

http://peewee.readthedocs.org/en/latest/peewee/cookbook.html#iterating-over-lots-of-rows