Django 1.8 アプリケーションがあり、db バックエンドとして pyodbc を使用して MsSQL データベースを使用しています (「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 倍遅くなります。何が原因でしょうか?