import sqlalchemy

engine = sqlalchemy.create_engine('mysql+pymysql://user:pass@host/db')
results = engine.execute('select * from large_table')

for result in results:
    process_result(result)

SQLAlchemy にて、上記のような、大きなテーブルから select してきて、その結果を何かしらの逐次処理にかけることがやりたくなりました。

execute の結果帰ってくるオブジェクトは ResultProxy ですが、これは、自分の理解だと DB のカーソルをラップしたようなものだと認識しており、なので、上記のコマンドはいい感じに iterator を通じて、必要な分だけ large_table からデータをフェッチし、それに対して process_result を実行してくれると思っていました。

しかし、上記のコマンドを実行したところ、これは大量のメモリを使用することがわかりました。具体的には、 engine.execute の段階で、 select 文の結果を、 results の中に全て fetch しているような動作をしているようです。

質問

  • SQLAlchemy にて、クエリの execute に対して、その結果をカーソル的に逐次処理したい場合、これはどのように実現できますか?