Я намагаюся покращити ефективність наступного запиту:
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 або я просто написав це неправильно? А по-друге, чи може хтось запропонувати поліпшення, якого я ще не пробував? FYI - це екземпляр Enterprise SQL Server 2008 R2 Enterprise.
EDIT: Ось посилання на початковий план виконання. Я також повинен зазначити, що моя велика проблема полягає в тому, що цей запит виконується 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
якщо стовпчик є нульовим. Якщо вона містить будь-які нулі, вам потрібно відняти 1.