我正在尝试改善以下查询的性能:
UPDATE [#TempTable]
SET Received = r.Number
FROM [#TempTable]
INNER JOIN (SELECT AgentID,
RuleID,
COUNT(DISTINCT (GroupId)) Number
FROM [#TempTable]
WHERE Passed = 1
GROUP BY AgentID,
RuleID
) r ON r.RuleID = [#TempTable].RuleID AND
r.AgentID = [#TempTable].AgentID
目前,根据我的测试数据,大约需要一分钟。对于此查询所驻留的整个存储过程的更改,我的输入量有限,但我可能可以让他们修改此查询。或添加索引。我尝试添加以下索引:
CREATE CLUSTERED INDEX ix_test ON #TempTable(AgentID, RuleId, GroupId, Passed)
它实际上使查询所花费的时间增加了一倍。我得到一个非聚集索引相同的效果。
我尝试将其重写如下,但没有任何效果。
WITH r AS (SELECT AgentID,
RuleID,
COUNT(DISTINCT (GroupId)) Number
FROM [#TempTable]
WHERE Passed = 1
GROUP BY AgentID,
RuleID
)
UPDATE [#TempTable]
SET Received = r.Number
FROM [#TempTable]
INNER JOIN r
ON r.RuleID = [#TempTable].RuleID AND
r.AgentID = [#TempTable].AgentID
接下来,我尝试使用这样的窗口功能。
UPDATE [#TempTable]
SET Received = COUNT(DISTINCT (CASE WHEN Passed=1 THEN GroupId ELSE NULL END))
OVER (PARTITION BY AgentId, RuleId)
FROM [#TempTable]
在这一点上,我开始得到错误
Msg 102, Level 15, State 1, Line 2
Incorrect syntax near 'distinct'.
所以我有两个问题。首先,您不能使用OVER子句执行COUNT DISTINCT还是我只是写错了?其次,有人可以建议我没有尝试过的改进吗?仅供参考,这是一个SQL Server 2008 R2 Enterprise实例。
编辑:这是原始执行计划的链接。我还应该注意,我的大问题是此查询正在运行30-50次。
https://onedrive.live.com/redir?resid=4C359AF42063BD98%21772
EDIT2:这是语句在注释中所要求的完整循环。我会定期与进行此操作的人员联系,以了解循环的目的。
DECLARE @Counting INT
SELECT @Counting = 1
-- BEGIN: Cascading Rule check --
WHILE @Counting <= 30
BEGIN
UPDATE w1
SET Passed = 1
FROM [#TempTable] w1,
[#TempTable] w3
WHERE w3.AgentID = w1.AgentID AND
w3.RuleID = w1.CascadeRuleID AND
w3.RulePassed = 1 AND
w1.Passed = 0 AND
w1.NotFlag = 0
UPDATE w1
SET Passed = 1
FROM [#TempTable] w1,
[#TempTable] w3
WHERE w3.AgentID = w1.AgentID AND
w3.RuleID = w1.CascadeRuleID AND
w3.RulePassed = 0 AND
w1.Passed = 0 AND
w1.NotFlag = 1
UPDATE [#TempTable]
SET Received = r.Number
FROM [#TempTable]
INNER JOIN (SELECT AgentID,
RuleID,
COUNT(DISTINCT (GroupID)) Number
FROM [#TempTable]
WHERE Passed = 1
GROUP BY AgentID,
RuleID
) r ON r.RuleID = [#TempTable].RuleID AND
r.AgentID = [#TempTable].AgentID
UPDATE [#TempTable]
SET RulePassed = 1
WHERE TotalNeeded = Received
SELECT @Counting = @Counting + 1
END
count
可为空的语义不同。如果它包含任何空值,则需要减去