2017-05-09 4 views
3

私は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()はページ分割されたクエリーセットでうまく機能しますか?

+0

クエリは、どのように長い間、彼らはむしろ全体の時間よりも、服用しているされているかを見ることは有用であろう。 – Alasdair

+0

@Alasdairご関心をお寄せいただきありがとうございます。私はあなたが要求する情報を提供するつもりですが、あなたが正確に何を意味するかはわかりません。 SQLリクエストについて話していますか? –

+1

はい、SQLクエリです。 Django Debugツールバーや 'connection.queries'を使ってこれを行うことができます。 – Alasdair

答えて

1

データベースにインデックスがないことを確認することが重要です。 Rna.upiフィールドにはdb_index=Trueがありますが、インデックスはデータベースに存在していますか?

select_relatedcount()クエリを遅くする場合、select_relatedのページ番号object_listを試してみることができます。

for object in rna_paginator.page(300).object_list.select_related(): 
    message = message + str(object.rna.upi) 
関連する問題