Django公司泡菜、垃圾(模型.查询)正在命中db

2024-09-30 22:24:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试pickle django查询对象以将其保存在Redis中。在

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)

以下是调试面板的跟踪(我使用延迟分页): 源查询是:

SELECT "san_material"."id", "san_material"."created_at", "san_material"."title", "san_material"."author", "san_material"."url", "san_material"."publication_datetime", "san_material"."text", "san_material"."size", "san_material"."source_id", "san_material"."material_type", "san_material"."updated_at", "san_material"."status", "san_material"."elastic_sync", "san_material"."tokens", "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"."detection_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"."detection_datetime" DESC LIMIT 51

但它是子查询命中数据库:

SELECT U0."material_id" FROM "san_materialdata" U0 WHERE U0."tag_id" IN (660)

在这里:

^{pr2}$

我怎样才能修好它?在

p.s i在def\u batch_setitems中测量了节省时间的参数:

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

3倍乘以2.5秒。为什么?在


Tags: keynameredisiddatetimetagselectmaterial
1条回答
网友
1楼 · 发布于 2024-09-30 22:24:59

Django query是lazy query的,但是让我来解释一下您写的内容:

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)

您可以通过在django中使用正确的连接来更正此问题:

我猜您的MaterialData模型将material作为material模型的外键。在

^{pr2}$

相关问题 更多 >