我有一个包含Profile
和Relationship
模型的数据库。我没有在模型中明确地链接它们(因为它们是第三方ID,并且它们可能在两个表中都不存在),但source
和target
字段映射到一个或多个{{1通过Profile
字段对象:
id
我的查询需要从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)
列中获取100个值的列表,这些值尚不存在Relationship.source
。然后,该列表将用于从第三方收集必要的数据。下面的查询有效,但随着表的增长(10m +),SubQuery变得非常大而且速度慢。
有关如何优化此建议的任何建议?后端是PostgreSQL,但如果可能的话我想使用原生的Django ORM。
编辑:有一个额外的复杂程度会导致查询速度变慢。并非所有ID都能保证返回成功,这意味着它们将继续“不存在”并使程序处于无限循环中。所以我添加了一个Profile.id
和filter
来输入前一批100中的最高order_by
。这将导致一些问题,因此最初错过它会道歉。
id
提前感谢任何建议!
答案 0 :(得分:0)
对于未来的搜索者,我在这里绕过了__in
查询,并且能够加快结果。
from django.db.models import Subquery
from django.db.models import Count # New
user = Profile.objects.get(handle="philsheard")
subq = Profile.objects.filter(profile_id=OuterRef("source")) # New queryset to use within Subquery
rels = Relationship.objects.order_by(
"source"
).annotate(
# Annotate each relationship record with a Count of the times that the "source" ID
# appears in the `Profile` table. We can then filter on those that have a count of 0
# (ie don't appear and therefore haven't yet been connected)
prof_count=Count(Subquery(subq.values("id")))
).filter(
target=user.id,
prof_count=0
).filter(
source__gt=max_id_from_previous_batch # An integer representing a previous `Relationship.source` id
).values_list(
"source", flat=True
)
我认为这更快,因为查询将在达到所需的100项后完成(而不是每次与1m + ID的列表进行比较)。