2016-07-27 4 views
1

私はRedjisに保存するためにdjango Queryオブジェクトをpickleしようとしています。ここでDjango pickle.dumps(model.query)hit db

materials = Material.objects.prefetch_related('tags_applied').prefetch_related('materialdata_set').prefetch_related('source') 
materials_ids = MaterialData.objects.filter(tag_id__in=tags).values_list('material_id', flat=True) 
materials = materials.filter(pk__in=materials_ids) 
key_name = SAMPLES_UUID + ':' + str(redis_uuid) 
redis_cl.set_key(key_name, pickle.dumps(materials.query)) 
redis_cl.expire(key_name, SAMPLES_TIMEOUT) 

debug_panelからのトレースは(私は怠惰なページネーションを使用)です: ソースクエリは次のとおりです。

SELECT "san_material" "ID"、 "san_material" "のcreated_at"、 」。 "author"、 "san_material"、 "url"、 "san_material"。 "publication_datetime"、 "san_material"。 "text"、 "san_material"。 "サイズ"、 " san_material "、" san_material "、" san_material "。" source_id "、 " san_material "。" material_type "、" san_material "。" updated_at "、 " san_material " "elastic_sync」、 "san_material"。 "トークン"、 "san_material"。 "detection_datetime"、 "san_material"。 "article_title"、 "san_material"。 "publication_datetime_article"、 "san_material"。 "author_article"、" san_material "highlight_data" FROM "san_material" WHERE( "san_material"。 "detect_datetime" BETWEEN '2016-07-01T00:00:00 + 03:00 ':: timestamptz AND ' 2016-07-27T10:39:00 +03:00 ':: timestamptz AND "san_material"。 "id" IN (SELECT U0。 "material_id" FROM "san_materialdata" U0 WHERE U0。 "tag_id" IN(660)))ORDER BY "san_material"検出日時 "DESC LIMIT 51

しかし、サブクエリヒットデシベルです。

/home/maxx/analize/san/utils.py in wrapper(82) 
    result = method_to_decorate(*args, **kwds) 
/home/maxx/analize/san/views/flux.py in flux(111) 
    redis_cl.set_key(key_name, pickle.dumps(materials.query)) 
/usr/lib/python2.7/pickle.py in dumps(1393) 
    Pickler(file, protocol).dump(obj) 
/usr/lib/python2.7/pickle.py in dump(225) 
    self.save(obj) 
/usr/lib/python2.7/pickle.py in save(333) 
    self.save_reduce(obj=obj, *rv) 
/usr/lib/python2.7/pickle.py in save_reduce(421) 
    save(state) 
/usr/lib/python2.7/pickle.py in save(288) 
    f(self, obj) # Call unbound method with explicit self 
/usr/lib/python2.7/pickle.py in save_dict(657) 
    self._batch_setitems(obj.iteritems()) 
/usr/lib/python2.7/pickle.py in _batch_setitems(675) 
    save(v) 
/usr/lib/python2.7/pickle.py in save(333) 
    self.save_reduce(obj=obj, *rv) 
/usr/lib/python2.7/pickle.py in save_reduce(421) 
    save(state) 
/usr/lib/python2.7/pickle.py in save(288) 
    f(self, obj) # Call unbound method with explicit self 
/usr/lib/python2.7/pickle.py in save_dict(657) 
    self._batch_setitems(obj.iteritems()) 
/usr/lib/python2.7/pickle.py in _batch_setitems(675) 
    save(v) 
/usr/lib/python2.7/pickle.py in save(288) 
    f(self, obj) # Call unbound method with explicit self 
/usr/lib/python2.7/pickle.py in save_list(604) 
    self._batch_appends(iter(obj)) 
/usr/lib/python2.7/pickle.py in _batch_appends(620) 
    save(x) 
/usr/lib/python2.7/pickle.py in save(333) 
    self.save_reduce(obj=obj, *rv) 
/usr/lib/python2.7/pickle.py in save_reduce(421) 
    save(state) 
/usr/lib/python2.7/pickle.py in save(288) 
    f(self, obj) # Call unbound method with explicit self 
/usr/lib/python2.7/pickle.py in save_dict(657) 
    self._batch_setitems(obj.iteritems()) 
/usr/lib/python2.7/pickle.py in _batch_setitems(675) 
    save(v) 
/usr/lib/python2.7/pickle.py in save(308) 
    rv = reduce(self.proto) 
/home/maxx/venv/analize/lib/python2.7/copy_reg.py in _reduce_ex(84) 
    dict = getstate() 
:U0 "TAG_ID" IN(660)ここで

"san_materialdata" U0 FROM

SELECT U0 "material_id"

どうすれば修正できますか? 2.5秒で

('Save obj time:', 2.5215649604797363, 'arg:', 'rhs') 
('Save obj time:', 2.5219039916992188, 'arg:', 'children') 
('Save obj time:', 2.5219550132751465, 'arg:', 'where') 

その3回:

p.s iはデフ_batch_setitemsに引数を保存する時間を測定しました。どうして?

+0

あなたのタグを管理するために 'django-taggit'または同様のアプリを使用していますか? JSONでタグ付きモデルをダンプするときも同様の問題がありました。何が起こったのは、タグがダンプされるたびに、実装された方法がクエリを生成したことです。私はpickleでそれを行う方法はわかりませんが、最終的にJSONをビルドするときにタグを '[tag.name(tag inname in mymodel.tags.all()]'で置き換える必要がありました。 – raphv

+0

ipdb – maxx

+0

OKのみを使用します。赤ちゃんに保存したいのはまさにそれですか?あなたがクエリーセット全体を漬けているなら、クエリーセットがどのように構築されているかを内部で保持し、互換性の問題があるかもしれません(https://docs.djangoproject.com/en/1.9/ref/models/querysets/#酸洗い)。データを保存したいだけなら、酸洗の代わりにシリアライゼーションを使う方が良いかもしれません:https://docs.djangoproject.com/en/1.9/topics/serialization/ – raphv

答えて

1

Djangoのクエリのは怠惰なクエリのですが、私はあなたが書かれているかを説明しましょう:

materials = Material.objects.prefetch_related('tags_applied' 
    ).prefetch_related('materialdata_set').prefetch_related('source') 


materials_ids = MaterialData.objects.filter(tag_id__in=tags).values_list('material_id', flat=True) 

# till now materials_id is queryset, means it will not hit DB. 
# as soon it execute next line of code it will hit db, because in next line you are using materials_ids. 

materials = materials.filter(pk__in=materials_ids) 

# So you can avoid hiting db if you are not required to use materials 
key_name = SAMPLES_UUID + ':' + str(redis_uuid) 
redis_cl.set_key(key_name, pickle.dumps(materials.query)) 
redis_cl.expire(key_name, SAMPLES_TIMEOUT) 

あなたが適切な使用してこれを修正することができますジャンゴに参加する:私はあなたがMaterialDataモデルがを持っていると思います

品目に資材としてモデルです。

materials = MaterialData.objects.filter(tag_id__in=tags).prefetch_related(
'material__tags_applied' 
).prefetch_related('material__materialdata_set').prefetch_related('material__source').values(*all values realted to mateials you can put here by adding materials__ before each material field *) 

# to fetch foreign key attribue you use field followed by duble underscore 

key_name = SAMPLES_UUID + ':' + str(redis_uuid) 
redis_cl.set_key(key_name, pickle.dumps(materials.query)) 
+0

同じです。助けてくれない – maxx

+2

サブクエリは '.filter()'に渡すと評価されません。 'material_ids'はサブクエリとして' materials'に埋め込まれていますが、単独では評価されません。これはpickleとのやりとりのために評価されるかもしれませんが、 'pickle.dumps()'で評価され、 '.filter()'に渡されるときは評価されません。 – knbk

関連する問題