最近的工作中实现了一个定时统计性能:须要按指定程序,从源表中取出数据,通过分组合并,插入指标表。
源表数据量相当大,有几千万行,显然不适宜一次性取出(如果是一次性的脚本,在大内存的机器上也是能够思考的,但定时工作每次启动都占用数十 GB 内存就太夸大了),须要分页查问。
但最后的实现中,采纳了一个封装好的分页库,单纯的全表查问,纯正依赖 limit 子句限度后果集窗口,形成的 SQL 语句相似这样:
select * from A order by x, y limit 30000, 10000
其中字段 x 和字段 y 是有联结索引的,每页返回 10000 条。
后果惨不忍睹,每页查问须要 40 秒能力返回,而这样的查问须要循环几千次,整整半天工夫都没执行完。
解决方案 也很简略,应用自定义的分页机制,基于字段 x 筛选实现分页:
select * from A where x > 30000 order by x, y limit 10000
留神:这里的 30000,只是示例,每次要把上一页最初一条的 x 值记下来,当做下一页 ”x > ?” 的判断条件。
python + sqlalchemy 的代码示例如下:
PAGE_SIZE = 10000
last_x = 0 # 这里假如 x 永远是大于零的整数,如果不是,初始化一个最小值
while last_x == 0 or len(records > 0):
# last_x == 0 这个条件,相当于判断是否第一次循环,这里其实有 do...while 语句更好,惋惜 python 没有
records = A.query.filter(A.x > last_x).order_by(A.x, A.y).limit(PAGE_SIZE)
last_x = records[-1].x
# do something