J'essaie d'améliorer les performances de la requête suivante:
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
Actuellement, avec mes données de test, cela prend environ une minute. J'ai une quantité limitée d'entrée dans les modifications de la procédure stockée dans laquelle réside cette requête, mais je peux probablement les amener à modifier cette seule requête. Ou ajoutez un index. J'ai essayé d'ajouter l'index suivant:
CREATE CLUSTERED INDEX ix_test ON #TempTable(AgentID, RuleId, GroupId, Passed)
Et cela a en fait doublé le temps nécessaire à la requête. J'obtiens le même effet avec un index NON CLUSTERED.
J'ai essayé de le réécrire comme suit sans effet.
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
Ensuite, j'ai essayé d'utiliser une fonction de fenêtrage comme celle-ci.
UPDATE [#TempTable]
SET Received = COUNT(DISTINCT (CASE WHEN Passed=1 THEN GroupId ELSE NULL END))
OVER (PARTITION BY AgentId, RuleId)
FROM [#TempTable]
À ce stade, j'ai commencé à obtenir l'erreur
Msg 102, Level 15, State 1, Line 2
Incorrect syntax near 'distinct'.
J'ai donc deux questions. Tout d'abord, ne pouvez-vous pas faire un COUNT DISTINCT avec la clause OVER ou l'ai-je simplement écrit de manière incorrecte? Et deuxièmement, quelqu'un peut-il suggérer une amélioration que je n'ai pas encore essayée? Pour info, il s'agit d'une instance SQL Server 2008 R2 Enterprise.
EDIT: Voici un lien vers le plan d'exécution d'origine. Je dois également noter que mon gros problème est que cette requête est exécutée 30 à 50 fois.
https://onedrive.live.com/redir?resid=4C359AF42063BD98%21772
EDIT2: Voici la boucle complète dans laquelle se trouve l'instruction comme demandé dans les commentaires. Je vérifie régulièrement avec la personne qui travaille avec cela le but de la boucle.
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
la source
count
si la colonne est nullable. S'il contient des valeurs nulles, vous devez soustraire 1.