Sto cercando di migliorare le prestazioni della seguente query:
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
Attualmente con i miei dati di test ci vogliono circa un minuto. Ho una quantità limitata di input per le modifiche su tutta la procedura memorizzata in cui risiede questa query, ma probabilmente posso farli modificare questa query. Oppure aggiungi un indice. Ho provato ad aggiungere il seguente indice:
CREATE CLUSTERED INDEX ix_test ON #TempTable(AgentID, RuleId, GroupId, Passed)
E in realtà ha raddoppiato il tempo impiegato dalla query. Ottengo lo stesso effetto con un indice NON CLUSTER.
Ho provato a riscriverlo come segue senza alcun effetto.
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
Successivamente ho provato a utilizzare una funzione di windowing come questa.
UPDATE [#TempTable]
SET Received = COUNT(DISTINCT (CASE WHEN Passed=1 THEN GroupId ELSE NULL END))
OVER (PARTITION BY AgentId, RuleId)
FROM [#TempTable]
A questo punto ho iniziato a ricevere l'errore
Msg 102, Level 15, State 1, Line 2
Incorrect syntax near 'distinct'.
Quindi ho due domande. Per prima cosa non puoi fare un COUNT DISTINCT con la clausola OVER o l'ho appena scritto in modo errato? E secondo, qualcuno può suggerire un miglioramento che non ho già provato? Cordiali saluti, questa è un'istanza di SQL Server 2008 R2 Enterprise.
EDIT: ecco un link al piano di esecuzione originale. Dovrei anche notare che il mio grande problema è che questa query viene eseguita 30-50 volte.
https://onedrive.live.com/redir?resid=4C359AF42063BD98%21772
EDIT2: Ecco il ciclo completo in cui si trova l'istruzione come richiesto nei commenti. Sto verificando con la persona che lavora regolarmente con questo riguardo allo scopo del loop.
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
se la colonna è nullable. Se contiene dei null è necessario sottrarre 1.