在我的数据库中,我有一对表(tableA
和tableB
),这两个表都有外键引用ID
中的同一列tableC
。我能够使用的SQL是
SELECT *
FROM tableA
INNER JOIN tableB on tableA.ID=tableB.ID
WHERE tableB.year=2011
查询
SELECT *
FROM tableA
INNER JOIN tableB on tableA.ID=tableB.ID AND tableB.year=2011
做了同样的事情
在Django中,我尝试使用代码
执行此操作subquery=tableB.objects.filter(year=2011).values_list(id, flat=True)
results=tableA.objects.filter(id__in=list(subquery))
如documentation中所述。我知道这有点不同,因为它只返回tableA
中的列,但我只会使用它们。 Django代码似乎很慢,我想部分是因为tableA
的每一行的集合成员资格测试,这是非常大的。有没有办法在不使用原始SQL的情况下在Django中加快速度(如果需要,我显然可以使用它)?
答案 0 :(得分:1)
看起来你的模特不是很“django”友好。你使用一对一的关系,你的表pk是外键吗? (如果没有,请在问题中发布您的架构)。 Django更喜欢你的表(模型)主键是唯一的自动增量整数而不是外键。
django明智地说这更好:class TableC(models.Model):
name = models.CharField(max_length=1000)
class TableA(models.Model):
tablec = models.OneToOneField(TableC)
class TableB(models.Model):
tablec = models.OneToOneField(TableC)
year = models.IntegerField()
请注意,所有字段都有一个(隐式)id字段,该字段是表的主键。现在执行:
TableA.objects.filter(tablec__tableb__year__exact=2011)
您实际上可以使用外键作为主键:
class TableC(models.Model):
name = models.CharField(max_length=1000)
class TableA(models.Model):
tablec = models.OneToOneField(TableC, primary_key=True, db_column='id')
class TableB(models.Model):
tablec = models.OneToOneField(TableC, primary_key=True, db_column='id')
year = models.IntegerField()
执行相同的查询。但是,这可能会在以后引起更多问题(“不保修”)。
答案 1 :(得分:1)
它很慢,因为它创建的查询可能看起来像
SELECT * FROM TableA WHERE ID IN (SELECT ID FROM TableB WHERE year=2011)
就像@Udi说的那样,如果你能通过添加外键来“django”来模仿模型,你会更好。否则,请使用RawSQL。这就是它的用途。
答案 2 :(得分:1)
不要将subquery
转换为列表。如果你刚刚这样做了:
results=tableA.objects.filter(id__in=subquery)
Django应该足够聪明,可以实际执行子查询,而不是两个单独的查询。