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

[Django] QuerySetのcacheの動きを確認

2008年10月1日

Djangoアプリ用のバッチ処理で、10万件前後のデータをアレコレするため、
若干性能的に配慮が必要かなと、クエリセットのキャッシュの動きを軽く追ってみた。

総論的な部分は下記のドキュメントを読んでもらうとして、動作確認した部分だけをつらつらと。
なお、Django-0.96.2でDBはMySQL-5.0です。

1. リレーションしたフィールドについてはsave時にもクエリを発行する
例えば、以下の例

sm = SomeModel()
# SomeModel#some_masterはForeignKeyField
sm.some_master = SomeMasterModel.objects.get(pk=1)
sm.save()

この場合のSomeMasterModelについてクエリが発行されるタイミングは
“SomeMasterModel.objects.get(pk=1)”の抽出時に1回と
“sm.save()”をした際に1回の、合計2回となりました。

2. QuerySetへのインデックス直指定時も毎回クエリを発行する
ModelManager#getは毎回クエリを発行するというのはドキュメントに書いて有りますが
インデックスの直指定時にも毎回発行してました。

SomeModel.objects.all()[0]

(というかインデックスの直指定自体が、getのラッパなのか?)

3. ModelManager#getはキャッシュさせられない?
というのも、
これ↓はo変数を評価時にqsに紐付くキャッシュを使ってくれるため
クエリ発行は最初の1回で済むのに対して・・・

qs = SomeModel.objects.all()
for o as qs:
print o

・・・これら↓は毎度クエリを発行してしまいます。
多分、

qs = SomeModel.objects.all()
print qs.get(pk=1)
print qs.get(pk=2)
print qs.get(pk=3)
# ... 以下略 ...
print qs[0]
print qs[1]
print qs[2]
# ... 以下略 ...

クエリセットをfor文で回した場合は
「クエリセットのリファインを行わずに」
「(通常getで行うように)個別のModelオブジェクトにアクセス可能」
・・・ということなので、キャッシュが使用されるということでしょうか?

まぁ、インデックスを張ればほぼ問題ない部分だろうと思われるので、
あんまり気にしても仕方ないんすけど。

うーむ、Django初心者もいいところなので、本当に正しいのかが我ながら疑わしい!!
・・・まぁいいや、以上。

参考リンク