Sql 由于子选择,查询速度较慢
我有几个SQL Server 2014查询,这些查询提取了一个数据集,在该数据集中,我们需要获得与该数据相关但标准不同的计数。我们通过一个子查询来实现这一点,但这大大降低了它的速度。到目前为止一切都很好,我们在数据库中获得了更多的数据。以下是查询:Sql 由于子选择,查询速度较慢,sql,sql-server,tsql,sql-server-2014,Sql,Sql Server,Tsql,Sql Server 2014,我有几个SQL Server 2014查询,这些查询提取了一个数据集,在该数据集中,我们需要获得与该数据相关但标准不同的计数。我们通过一个子查询来实现这一点,但这大大降低了它的速度。到目前为止一切都很好,我们在数据库中获得了更多的数据。以下是查询: SELECT T.*, ISNULL((SELECT COUNT(1) FROM EventRegTix ERT, EventReg ER WHERE ER.EventRegID =
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
更改为实际的ticket#(例如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;
正确、明确、标准的联接
语法不会提高性能;这就是正确的语法COUNT(*)
无法返回NULL
值,因此不需要COALESCE()
或类似的函数
你需要索引。最明显的是Tickets(EventID,DeleteFlag,ActiveFlag,OrderNumber)
,EventRegTix(TicketID,EventRegID)
,和EventReg(EventRegID,OrderCompleteFlag)
我将其写成:
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;
正确、明确、标准的联接
语法不会提高性能;这就是正确的语法COUNT(*)
无法返回NULL
值,因此不需要COALESCE()
或类似的函数
你需要索引。最明显的是
Tickets(EventID、DeleteFlag、ActiveFlag、OrderNumber)
,EventRegTix(TicketID、EventRegID)
,以及EventReg(EventRegID、OrderCompleteFlag)
我会尝试使用外部应用:
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;
而且,显然您需要索引票证(EventID、DeleteFlag、ActiveFlag、OrderNumber)、EventRegTix(TicketID、EventRegID)和EventReg(EventRegID、OrderCompleteFlag)
来获得性能。我会尝试使用外部应用
:
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;
显然,您需要索引票证(EventID、DeleteFlag、ActiveFlag、OrderNumber)、EventRegTix(TicketID、EventRegID)和EventReg(EventRegID、OrderCompleteFlag)
来获得性能。修复了此问题-查询时间从5秒以上缩短到1/2秒或更短。问题是:
1) 没有索引。不知道所有FK字段也需要索引。我索引了我们加入的所有字段或在WHERE子句中的所有字段
2) 使用SQL执行计划查看瓶颈所在的位置。告诉我没有索引,因此1)以上!:)
谢谢你们的帮助,希望这篇文章能帮助其他人
丹尼斯
PS:也更改了语法 修复了此问题-查询时间从5秒以上缩短到1/2秒或更短。问题是:
1) 没有索引。不知道所有FK字段也需要索引。我索引了我们加入的所有字段或在WHERE子句中的所有字段
2) 使用SQL执行计划查看瓶颈所在的位置。告诉我没有索引,因此1)以上!:)
谢谢你们的帮助,希望这篇文章能帮助其他人
丹尼斯
PS:也更改了语法 什么版本的SQL Server?为什么不简单地将连接保留到EventRegTix和EventReg,而不是子查询。此外,您真的应该开始使用ANSI-92样式联接。它们已经存在了25年多了。旁注:这种老式的连接语法已经有25年的历史了。应该使用新样式联接。(从表A作为内部联接表B作为A.Id=B.Id…)您可以发布执行计划吗?执行计划指出了问题-EventRegID的EventRegTix表上没有索引(它是一个FK)。现在索引。。。很快。非常感谢。什么版本的SQL Server?为什么不简单地将连接保留到EventRegTix和EventReg,而不是子查询。此外,您真的应该开始使用ANSI-92样式联接。它们已经存在了25年多了。旁注:这种老式的连接语法已经有25年的历史了。应该使用新样式联接。(从表A作为内部联接表B作为A.Id=B.Id…)您可以发布执行计划吗?执行计划指出了问题-EventRegID的EventRegTix表上没有索引(它是一个FK)。现在索引。。。很快。非常感谢。“您需要索引。”此查询不会更快。我不知道还有什么可以索引??“你需要索引。”这个查询没有更快。我不知道还需要索引什么??您是否需要对任何有条件的字段进行索引?我不是DBA(!!),但我不认为真/假字段需要索引。这是我可能错过的一个。FK的索引是默认的还是仅仅是PK?呃,我想这是我的问题。默认情况下,FK没有索引,让我索引并返回到这个问题。谢谢您是否需要任何字段上的索引,这些字段都有相应的条件?我不是DBA(!!),但我不认为真/假字段需要索引。这是我可能错过的一个。FK的索引是默认的还是仅仅是PK?呃,我想这是我的问题。默认情况下,FK没有索引,让我索引并返回到这个问题。谢谢您可能需要阅读和包含的列。是的,将进行审阅您可能需要阅读和包含的列。是的,将进行审阅