PythonでSQLiteのデータベースからデータを抜き取るときには何種類か方法がある。
- fetchallで一気に取得する方法
- fetchoneを繰り返す方法
- 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/