我有一个 Django 1.8 应用程序,我正在使用一个 MsSQL 数据库,以 pyodbc 作为数据库后端(使用“django-pyodbc-azure”模块)。
我有以下型号:
class Branch(models.Model):
name = models.CharField(max_length=30)
startTime = models.DateTimeField()
class Device(models.Model):
uid = models.CharField(max_length=100, primary_key=True)
type = models.CharField(max_length=20)
firstSeen = models.DateTimeField()
lastSeen = models.DateTimeField()
class Session(models.Model):
device = models.ForeignKey(Device)
branch = models.ForeignKey(Branch)
start = models.DateTimeField()
end = models.DateTimeField(null=True, blank=True)
我需要查询会话模型,并且我想排除一些具有特定设备值的记录。所以我发出以下查询:
sessionCount = Session.objects.filter(branch=branch)
.exclude(device__in=badDevices)
.filter(end__gte=F('start')+timedelta(minutes=30)).count()
badDevices 是一个包含大约 60 项的设备 ID 的预填充列表。
badDevices = ['id-1', 'id-2', ...]
此查询大约需要 1.5 秒才能完成。如果我从查询中删除排除项,大约需要 250 毫秒。
我为这个查询集打印了生成的 sql,并在我的数据库客户端中进行了尝试。在那里,两个版本都在大约 250 毫秒内执行。
这是生成的 SQL:
SELECT [session].[id], [session].[device_id], [session].[branch_id], [session].[start], [session].[end]
FROM [session]
WHERE ([session].[branch_id] = my-branch-id AND
NOT ([session].[device_id] IN ('id-1', 'id-2', 'id-3',...)) AND
DATEPART(dw, [session].[start]) = 1
AND [session].[end] IS NOT NULL AND
[session].[end] >= ((DATEADD(second, 600, CAST([session].[start] AS datetime)))))
因此,在数据库级别使用排除似乎不会影响查询性能,但在 django 中,如果我添加排除部分,查询运行速度会慢 6 倍。这可能是什么原因造成的?