sql - 运行 SQL 查询超时

标签 sql sql-server django sql-server-2008

我尝试使用 django ORM 的聚合功能在 MSSQL 2008R2 数据库上运行查询,但我不断收到超时错误。失败的查询(由 django 生成)如下。我尝试过直接在 SQL Management Studio 上运行它,它可以工作,但需要 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]

奇怪的是,如果我注释掉上面的任意两行,它的运行时间将少于 1 秒,但删除哪行似乎并不重要(尽管显然我无法删除连接而不需要删除相关的 SELECT 行)。

编辑3:

生成这个的Python代码是:

User.objects.annotate(
    Count('tickets_captured'), 
    Count('assigned_tickets'), 
    Count('tickets_watched')
)

查看执行计划可以看出,SQL Server 首先对所有表进行交叉联接,产生大约 2.8 亿行和 6Gb 的数据。我认为这就是问题所在,但为什么会发生呢?

最佳答案

SQL Server 正在完全按照要求执行操作。不幸的是,Django 没有生成您想要的正确查询。看来您需要计算不同的数,而不仅仅是计算: Django annotate() multiple times causes wrong answers

至于为什么查询会这样工作:查询表示将四个表连接在一起。假设作者有 2 个捕获的票证、3 个分配的票证和 4 个观看的票证,则连接将返回 2*3*4 个票证,每个票证组合一个。不同的部分将删除所有重复项。

关于sql - 运行 SQL 查询超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17358372/

相关文章:

Mysql如何进行左连接、分组并仅计算唯一的左列行

sql - 带有 WHERE 子句的 VBA SQL 查询

同一对象中的 SQL Server 根 + FOR JSON 路径

sql-server - 我想在 SQL Server 2012 中优化查询

php - PHP/SQL 中的处理时间

mysql - 外键无法正常工作

sql-server - SQL Server 2012 CLR 程序集 - 参数计数不匹配

python - Django:没有名为 django.core.management 的模块

python - SynapsePay 和 Django 用户问题的冲突实例

django - 使用 jinja2 渲染模板时如何过滤 html 标记?