私は10万行それぞれに2つの関連のモデルを持っており、他方に50の000それらの一つの項目とアクセスに関連するデータを効率的にページ分割要求を実行したい:Django:Paginatorでselect_related()を効果的に使用する方法は?
class RnaPrecomputed(models.Model):
id = models.CharField(max_length=22, primary_key=True)
rna = models.ForeignKey('Rna', db_column='upi', to_field='upi', related_name='precomputed')
description = models.CharField(max_length=250)
class Rna(models.Model):
id = models.IntegerField(db_column='id')
upi = models.CharField(max_length=13, db_index=True, primary_key=True)
timestamp = models.DateField()
userstamp = models.CharField(max_length=30)
あなたが見ることができるように、RnaPrecomputed
外部キーを介してRNA
に関連付けられています。ここでは、RnaPrecomputed
の50 000項目の特定のページを取得し、それに対応するRna
を対応させたいと考えています。私はselect_related()
コールなしでこれを行うと、N + 1要求の問題を期待します。ここではタイミングは以下のとおりです。
参考のために、私は全く関連のモデルには触れませんが、まず:
rna_paginator = paginator.Paginator(RnaPrecomputed.objects.all(), 50000)
message = ""
for object in rna_paginator.page(400).object_list:
message = message + str(object.id)
は取ります
real 0m12.614s
user 0m1.073s
sys 0m0.188s
を今、私は」関連するモデルのデータにアクセスしよう:
rna_paginator = paginator.Paginator(RnaPrecomputed.objects.all(), 50000)
message = ""
for object in rna_paginator.page(400).object_list:
message = message + str(object.rna.upi)
おそらく私は、N + 1の要求の問題を抱えている、たくさんある
real 2m27.655s
user 1m20.194s
sys 0m4.315s
を、そう:
それがかかります。
しかし、今は、私が使用している場合select_related()
は、
rna_paginator = paginator.Paginator(RnaPrecomputed.objects.all().select_related('rna'), 50000)
message = ""
for object in rna_paginator.page(400).object_list:
message = message + str(object.rna.upi)
それはもっとかかります:
real 7m9.720s
user 0m1.948s
sys 0m0.337s
だから、何とかselect_related()
ではなく、より速くそれらを作るの、3倍遅く、物事を作りました。そしておそらくそれがなければ、私はN + 1要求を持っているので、RnaPrecomputed
の各エントリに対して、Django ORMはおそらく対応するRna
をフェッチするためにデータベースへの追加要求をしなければならないでしょうか?
私は間違って何をしていますか?select_related()
はページ分割されたクエリーセットでうまく機能しますか?
クエリは、どのように長い間、彼らはむしろ全体の時間よりも、服用しているされているかを見ることは有用であろう。 – Alasdair
@Alasdairご関心をお寄せいただきありがとうございます。私はあなたが要求する情報を提供するつもりですが、あなたが正確に何を意味するかはわかりません。 SQLリクエストについて話していますか? –
はい、SQLクエリです。 Django Debugツールバーや 'connection.queries'を使ってこれを行うことができます。 – Alasdair