経緯
モデルのバックアップを取るために以下のStack Overflowの記事を参考にしてCSV出力するようにしていたのだが、気づいたらすごい時間がかかるようになっていた。(2000件の出力に30秒以上)
Google Cloud Platform上で動かしていたので、60秒以上経過するとリクエストが500エラーになり困っていた。
原因
問題となるモデルは以下のように複数の外部参照を持つものだった。つまり、getattr(instance, f)
でフィールドへのアクセスを行うとDB検索が行われていた。
class History(models.Model):
_from = models.ForeignKey(Profile, related_name='_from')
_to = models.ForeignKey(Profile, related_name='_to')
parent = models.ForeignKey(u'self', null=True)
解決方法
外部参照は参照先を取ってくるのではなく、参照IDをCSVに出力するようにした。
元々のコード
field_names = [f.name for f in model._meta.fields]
ForeignKeyはIDを出力するようにしたもの(かなりかっこわるいコード)
field_names = [f.name if type(f) is not ForeignKey else f.name + '_id' for f in model._meta.fields]
追加のDB検索がなくなったので先のHistory 2000件でも1秒以下で処理できるようになった。