PythonでSQLiteのデータベースからデータを抜き取るときには何種類か方法がある。

  1. fetchallで一気に取得する方法
  2. fetchoneを繰り返す方法
  3. fetchmanyで数行ずつ取得する方法

である。

fetchoneはダルいから、いままではfetchallを使っていた。
単純に気持ちの問題なんだけれども、根こそぎぶっこ抜いてリストにいったん入れてしまえば、あとはフッツーのPythonで流儀で操作できるからである。
しかし。この方法には問題がある。
fetchallで全部を取り出した先はどこかと言えば、メモリである。
つまり、データベースが巨大になるほど、メモリをバカ食いするわけである。
これはたまらん。

そこで以下のようにする。

def getAllRecords(cursor, arraysize=1000):
    while True:
        records = cursor.fetchmany(arraysize)
        if not records:
            break
        for record in records:
            yield record

データベースから1000行ずつ取り出し、かつ、1行ずつyieldする。
メモリ使用量も抑えて、かつスピードも出る方法である。

元ネタは以下。
Use generators for fetching large db record sets (Python recipe)
http://code.activestate.com/recipes/137270-use-generators-for-fetching-large-db-record-sets/