2016-03-28 4 views
2

私はこれに類似のDjangoコード持っている:私はbulk_createを使用してModel2への挿入を最適化しなかった最適化ジャンゴ取得クエリ

for obj in some_list: 
    m1obj = Model1.objects.get(a=obj.a, b=obj.b, c=obj.c) 
    Model2(m1=m1obj, d=obj.d, e='foo').save() 

を、しかし、これはまだ理由getModel1から(〜45秒の痛々しいほど遅いです3kインサートの場合)。

は、私も追加してみました:

class Meta: 
    index_together = [ 
     ('a', 'b', 'c'), 
    ] 
    unique_together = [ 
     ('a', 'b', 'c'), 
    ] 

unique_togetherは少し助け、index_togetherはあまり影響を与えていないようでした。

私はこの行うための面倒な回避策があります。例えば、私は1つ以上のキーで順必要なすべてのオブジェクトを取得

  1. フィルターModel1を、 order_by('a', 'b')を呼び出し、Djangoが結果をキャッシュしていることを確認してください。等...最初aその後、bを検索するlen()
  2. 使用バイナリサーチ(from bisect import bisect_left)(これだけ反復ずっと少ないb sおよびc sがありますが、同じである。

これは、挿入時間を短縮より良い、クリーンでこれを行うには、保守の方法が存在しなければならない秒3 の上に!

JUSする。任意の提案ですか? は、Djangoのキャッシュクエリ結果内(スマート)を取得/フィルタリングする方法はありますか?

EDITd=obj.dd='foo'を変更 - 任意の一括取得は、それがそうでなければ、私はモデル2エントリを作成することはできません属するタプルにマップできする必要があります。

答えて

0

必要な結果のみをフェッチし、後でソートやバイナリ検索を行う必要がない単一のクエリ(here)を作成できます。

私はそれがあなたがすでにやっているものよりも速くなるかどうかわからないので、私はそれをテストしていない。また、SQLクエリが大きい場合(some_listのレコード数に従って)、このクエリは、パラメータmax_allowed_packet(既定値は16MB、here)でMySQL設定で定義されたサイズを超えると、エラーを発生させる可能性があります。

import operator 
from django.db.models import Q 
query = reduce(operator.or_, (Q(a=obj.a, b=obj.b, c=obj.c) for x in values)) 
model1_objs = Model1.objects.filter(query) 

その後、Model2bulk_createを行うことができます。

Model2.objects.bulk_create([ 
    Model2(m1=m1, d='foo', e='bar') 
    for m1 in model1_objs 
]) 
+0

は残念ながら、あなたの提案は、 '取得()'順次行うよりもはるかに遅いです。私は3分以上それをやめた。また、私の編集で述べたように、パラメータ 'd'と 'e'が一定であれば、これはうまくいきましたか?それらはそうではないので、DBクエリは注文を保証しないので、 'model1_objs'を正しい' obj.d'にマップする方法はありません。 – mibm

0

Model1には何行ありますか?それが比較的小さい場合(50k未満)、フィルタを使用してすべてをフェッチし、Pythonのタプルを比較できます。

「some_list」は小さなリスト(100未満)です.Qキーワードを使用するとすべてを一度にフィルタリングできます。

first = some_list.pop() 
conditions = Q(a=first.a, b=first.b, c=first.c) 
for obj in some_list: 
    conditions |= Q(a=obj.a, b=obj.b, c=obj.c) 

Model1.objects.filter(conditions) # this will get your all the Model1 from ur list 

Qオブジェクト参考:https://docs.djangoproject.com/en/1.9/ref/models/querysets/#q-objects

+0

この解決策は、@ muhammad-tahirが提案したものと同じです。 3Kの行については、私は数分後にクエリを殺しました。小規模なグループでは、個別のクエリよりもはるかに高速ではありません(まったく)。私は回避策を改善してテーブルの行マップをタプル化しましたが、高速で読みやすくなりましたが、行が100Kで3Kでないとメモリの問題に遭遇するかもしれません... – mibm