由于 Sub Select 导致查询缓慢
Slow Query Due to Sub Select
我有几个 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
table 的关系。如果我将 T.TicketID
更改为实际票号(例如 999),查询速度会快得多。
我试图将这些查询合并为一个,但由于子查询中还有其他字段,我无法使其正常工作。我在玩
COUNT(1) OVER (PARTITION BY T.TicketID) AS NumTicketsSold
但也想不通。
如有任何帮助,我们将不胜感激!
我会这样写:
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(*)
不能 return NULL
值,因此不需要 COALESCE()
或类似的函数。
您需要索引。最明显的是 Tickets(EventID, DeleteFlag, ActiveFlag, OrderNumber)
、EventRegTix(TicketID, EventRegID)
和 EventReg(EventRegID, OrderCompleteFlag)
。
我会尝试 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)
来获得性能。
修复了这个 - 查询从 5+ 秒减少到 1/2 秒或更少。问题是:
1) 没有索引。不知道所有 FK 字段也需要索引。我索引了我们加入的或在 WHERE 子句中的所有字段。
2) 使用 SQL 执行计划查看瓶颈所在的位置。告诉我没有索引,因此 1) 以上! :)
感谢大家的帮助,希望这 post 对其他人有所帮助。
丹尼斯
PS: 也改变了语法!
我有几个 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
table 的关系。如果我将 T.TicketID
更改为实际票号(例如 999),查询速度会快得多。
我试图将这些查询合并为一个,但由于子查询中还有其他字段,我无法使其正常工作。我在玩
COUNT(1) OVER (PARTITION BY T.TicketID) AS NumTicketsSold
但也想不通。
如有任何帮助,我们将不胜感激!
我会这样写:
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(*)
不能 return NULL
值,因此不需要 COALESCE()
或类似的函数。
您需要索引。最明显的是 Tickets(EventID, DeleteFlag, ActiveFlag, OrderNumber)
、EventRegTix(TicketID, EventRegID)
和 EventReg(EventRegID, OrderCompleteFlag)
。
我会尝试 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)
来获得性能。
修复了这个 - 查询从 5+ 秒减少到 1/2 秒或更少。问题是:
1) 没有索引。不知道所有 FK 字段也需要索引。我索引了我们加入的或在 WHERE 子句中的所有字段。
2) 使用 SQL 执行计划查看瓶颈所在的位置。告诉我没有索引,因此 1) 以上! :)
感谢大家的帮助,希望这 post 对其他人有所帮助。
丹尼斯
PS: 也改变了语法!