【发布时间】:2018-02-20 15:36:06
【问题描述】:
我有一个包含Profile 和Relationship 模型的数据库。我没有在模型中明确链接它们(因为它们是第三方 ID,它们可能还不存在于两个表中),但 source 和 target 字段通过 @ 映射到一个或多个 Profile 对象987654326@字段:
from django.db import models
class Profile(models.Model):
id = models.BigIntegerField(primary_key=True)
handle = models.CharField(max_length=100)
class Relationship(models.Model):
id = models.AutoField(primary_key=True)
source = models.BigIntegerField(db_index=True)
target = models.BigIntegerField(db_index=True)
我的查询需要从 Relationship.source 列中获取 100 个值的列表,这些值尚不作为 Profile.id 存在。然后,该列表将用于从第三方收集必要的数据。下面的查询有效,但随着表的增长(10m+),子查询变得非常大而且速度很慢。
关于如何优化它的任何建议?后端是 PostgreSQL,但如果可能的话,我想使用原生 Django ORM。
编辑:有额外的复杂性会导致慢查询。并非所有 ID 都能保证返回成功,这意味着它们将继续“不存在”并使程序陷入无限循环。所以我添加了一个filter 和order_by 来输入前一批100 个中最高的id。这将导致一些问题,所以很抱歉最初错过了它。
from django.db.models import Subquery
user = Profile.objects.get(handle="philsheard")
qs_existing_profiles = Profiles.objects.all()
rels = TwitterRelationship.objects.filter(
target=user.id,
).exclude(
source__in=Subquery(qs_existing_profiles.values("id"))
).values_list(
"source", flat=True
).order_by(
"source"
).filter(
source__gt=max_id_from_previous_batch # An integer representing a previous `Relationship.source` id
)
提前感谢您的任何建议!
【问题讨论】:
-
好吧,
IN查询不是最佳选择,尤其是 10M+ 行。尝试将源作为外键。或者使用 ANY(...) 以获得更快的结果。 -
谢谢@style。在 Django ORM 的上下文中,我不熟悉
ANY()。能举个简单的例子吗? -
我不确定如何在 django ORM 中执行此操作。或者是否可能,但您可以将其添加为本机查询。另一种解决方案是在插入新关系时对其进行分析,并具有
related_to_profile的布尔字段 - 这样您就可以查询它
标签: python django django-orm