子选择导致查询缓慢

时间:2018-10-19 13:55:22

标签: sql sql-server tsql sql-server-2014

我有几个SQL Server 2014查询,这些查询会拉回一个数据集,在此我们需要对相关但不同的条件以及该数据进行计数。我们使用子查询来执行此操作,但这极大地降低了它的速度。到现在为止还不错,我们可以在数据库中获取更多的数据。这是查询:

SELECT 
    T.*, 
    ISNULL((SELECT COUNT(1)
            FROM EventRegTix ERT, EventReg ER
            WHERE ER.EventRegID = ERT.EventRegID 
              AND ERT.TicketID = T.TicketID
              AND ER.OrderCompleteFlag = 1), 0) AS NumTicketsSold
FROM 
    Tickets T 
WHERE 
    T.EventID = 12345
    AND T.DeleteFlag = 0 
    AND T.ActiveFlag = 1
ORDER BY 
    T.OrderNumber ASC

我可以肯定,这主要是由于子查询外部与Tickets表之间的关系所致。如果我将T.TicketID更改为实际的票证号(例如999),则查询会更快。

我试图将这些查询合并为一个查询,但是由于子查询中还有其他字段,因此我无法使其正常工作。我在玩

COUNT(1) OVER (PARTITION BY T.TicketID) AS NumTicketsSold

但也无法弄清楚。

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:5)

我会这样写:

SELECT T.*, 
       (SELECT COUNT(1)
        FROM EventRegTix ERT JOIN
             EventReg ER
             ON ER.EventRegID = ERT.EventRegID 
        WHERE ERT.TicketID = T.TicketID AND ER.OrderCompleteFlag = 1
      ) AS NumTicketsSold
FROM Tickets T 
WHERE T.EventID = 12345 AND
      T.DeleteFlag = 0 AND
      T.ActiveFlag = 1
ORDER BY T.OrderNumber ASC;

正确,明确,标准 JOIN语法不会提高性能;这只是正确的语法。 COUNT(*)无法返回NULL的值,因此不需要COALESCE()或类似的函数。

您需要索引。显而易见的是在Tickets(EventID, DeleteFlag, ActiveFlag, OrderNumber)EventRegTix(TicketID, EventRegID)EventReg(EventRegID, OrderCompleteFlag)上。

答案 1 :(得分:1)

我会尝试使用OUTER APPLY

SELECT T.*, T1.*
FROM Tickets T OUTER APPLY
     (SELECT COUNT(1) AS NumTicketsSold
      FROM EventRegTix ERT JOIN
           EventReg ER
           ON ER.EventRegID = ERT.EventRegID 
        WHERE ERT.TicketID = T.TicketID AND ER.OrderCompleteFlag = 1
      ) T1
WHERE T.EventID = 12345 AND
      T.DeleteFlag = 0 AND
      T.ActiveFlag = 1
ORDER BY T.OrderNumber ASC;

显然,您需要索引Tickets(EventID, DeleteFlag, ActiveFlag, OrderNumber), EventRegTix(TicketID, EventRegID), and EventReg(EventRegID, OrderCompleteFlag)才能获得性能。

答案 2 :(得分:0)

解决了此问题-查询时间从5秒以上缩短到1/2秒或更短。问题是:

1)没有索引。也不知道所有FK字段都需要索引。我索引了所有我们加入或在WHERE子句中的字段。

2)使用SQL执行计划查看瓶颈所在的位置。告诉我没有索引,因此在1)以上! :)

感谢您的所有帮助人员,希望本文能对其他人有所帮助。

丹尼斯

PS:也更改了语法!