django ORM の集計機能を使用して MSSQL 2008R2 データベースでクエリを実行しようとしていますが、タイムアウト エラーが発生し続けます。失敗するクエリ (django によって生成された) は以下のとおりです。SQL管理スタジオを指示して実行しようとしましたが、動作しますが、3.5分かかります
必要のない一連のフィールドを集約しているように見えますが、実際にはそれほど時間がかかるはずですが、そうではありません。データベースもそれほど大きくなく、auth_user
9 件のレコードがticket_ticket
あり、1210 件、ticket_watchers
1876 件あります。足りないものはありますか?
SELECT
[auth_user].[id],
[auth_user].[password],
[auth_user].[last_login],
[auth_user].[is_superuser],
[auth_user].[username],
[auth_user].[first_name],
[auth_user].[last_name],
[auth_user].[email],
[auth_user].[is_staff],
[auth_user].[is_active],
[auth_user].[date_joined],
COUNT([tickets_ticket].[id]) AS [tickets_captured__count],
COUNT(T3.[id]) AS [assigned_tickets__count],
COUNT([tickets_ticket_watchers].[ticket_id]) AS [tickets_watched__count]
FROM
[auth_user]
LEFT OUTER JOIN [tickets_ticket] ON ([auth_user].[id] = [tickets_ticket].[capturer_id])
LEFT OUTER JOIN [tickets_ticket] T3 ON ([auth_user].[id] = T3.[responsible_id])
LEFT OUTER JOIN [tickets_ticket_watchers] ON ([auth_user].[id] = [tickets_ticket_watchers].[user_id])
GROUP BY
[auth_user].[id],
[auth_user].[password],
[auth_user].[last_login],
[auth_user].[is_superuser],
[auth_user].[username],
[auth_user].[first_name],
[auth_user].[last_name],
[auth_user].[email],
[auth_user].[is_staff],
[auth_user].[is_active],
[auth_user].[date_joined]
HAVING
(COUNT([tickets_ticket].[id]) > 0 OR COUNT(T3.[id]) > 0 )
編集:
関連するインデックスは次のとおりです (クエリで使用されていないものを除く)。
auth_user.id (PK)
auth_user.username (Unique)
tickets_ticket.id (PK)
tickets_ticket.capturer_id
tickets_ticket.responsible_id
tickets_ticket_watchers.id (PK)
tickets_ticket_watchers.user_id
tickets_ticket_watchers.ticket_id
編集2:
少し実験した後、次のクエリが実行速度を遅くする最小のクエリであることがわかりました。
SELECT
COUNT([tickets_ticket].[id]) AS [tickets_captured__count],
COUNT(T3.[id]) AS [assigned_tickets__count],
COUNT([tickets_ticket_watchers].[ticket_id]) AS [tickets_watched__count]
FROM
[auth_user]
LEFT OUTER JOIN [tickets_ticket] ON ([auth_user].[id] = [tickets_ticket].[capturer_id])
LEFT OUTER JOIN [tickets_ticket] T3 ON ([auth_user].[id] = T3.[responsible_id])
LEFT OUTER JOIN [tickets_ticket_watchers] ON ([auth_user].[id] = [tickets_ticket_watchers].[user_id])
GROUP BY
[auth_user].[id]
奇妙なことに、上記の任意の 2 行をコメント アウトすると、1 秒未満で実行されますが、どの行を削除しても問題ないように思われます (ただし、関連する行を削除せずに結合を削除することはできません)。行を選択します)。
編集3:
これを生成した python コードは次のとおりです。
User.objects.annotate(
Count('tickets_captured'),
Count('assigned_tickets'),
Count('tickets_watched')
)
実行計画を見ると、SQL Server が最初にすべてのテーブルでクロス結合を行っていることがわかります。その結果、約 2 億 8000 万行と 6Gb のデータが生成されます。ここに問題があると思いますが、なぜそれが起こっているのですか?