旧それなりブログの跡地、画像やスタイルやJSなどが壊れてることがあります。

[Django, MySQLdb] connection.cursorがメモリを掴む

2008年11月30日

Model.objects.getが何かをキャッシュして
メモリを消費しているのかと思っていましたが
ちゃんと調べると、MySQLdb.connection.cursorを使ってSQLを発行すると
メモリを消費していくよう。

何にメモリを使ってるのかな?というと
コチラのサイトに回答があった。

execute()は、複数回実行するとそのたびにSQL文を構文解析しているように見えますが、
このexecute()は一般的な実装では一度解析されたSQL文をキャッシュしていて、
繰り返し同じSQL文が実行されるときには解析の手間を省いて高速化が図られているそうです。

解決方法として、
できれば cursor.executeによって消費されたメモリを開放する手段を
探したかったのですが
MySQLdbのソースまでひっくり返して読んでも、
そういうインターフェースが見つかりませんでした。

もう、しゃーーーないので、
MySQLdb.connection.queryを使ってクエリを発行したところ
メモリを消費しないクエリを発行することができました! ヒャッフー!!

以下、Djangoで書く時の例

from django.db import connection
connection.connection.query("BEGIN")
connection.connection.query("UPDATE some_table SET some_column = 1 WHERE id = 1")
connection.connection.query("COMMIT")

くっそー、こんなんに半日も掛かりやがった・・・。
カ、カカロット・・・。

【追記】
connection.connection.query をいきなり呼ぶと、
DBとの接続が無く、これは自動で繋げてくれないので、queryを呼べない模様。
よって、接続してない状態だったら
connection.cursor() を空で呼ぶ等の対応で、無理矢理繋げる必要がある(・・・模様、あんまり調べてない)。

つまり、前の状況により接続をしてないということが考えられるので、
特に理由が無い場合は、上記の呼び方は止めた方がいいってことすな。