SqlAlchemyのyield_perというメソッド
Railsで言う、find_in_batchesですかね。大量データをselectする時に結果を全部メモリに格納することなく逐次処理してくれる素敵メソッドですね。
てっきりlimitとかoffsetとかをよしなにハンドリングしてくれるメソッドかと思ったら、そんなことなくて、selectした結果をストリームとして処理するメソッドなのですね。
SQLのログを見て、思い(込んだ)通りにSQLが出てこないことに悩む人が、きっと僕以外にもいるだろうと思ったのでメモしておきますね。
念のため使い方メモ
sess = Session(engine)
for obj in sess.query(Customer).filter_by(ownd_uid = n).yield_per(10):
hogehoge(obj)
このように書いておくとfilterの条件で選択したレコードが大量にあっても10件ずつselectしながら処理をしてくれるので、selectの結果を全部メモリに載せることなく逐次処理してくれます。
最高ですね。
おや?N本の接続を使っている?
MySQLの方でshow processlistしてみると、yield_perで呼び出しているコネクションはそれぞれ一本のコネクションを貼っているようですね。言われてみればそうか。
一番最初の945秒かかってるのが最上位のループなんですが、はてconnect_timeoutで切れないのだろうか...。(切れそうな気がする)
こういうの大量データを使ってないと見えないところだったりしますので、エラーが出たら、使い方について継続的にメモしていきますね。
結果:接続エラーは出ませんでした。
1〜2時間かかる処理でしたが、問題なく終わりました。
もしかして、長時間の接続をキープしてるとshow processlistにクエリ出なくなったりします?!
是非、MySQL側でどのような処理になっているのか、挙動を調べてみてください!