Construire une requête.
La requête unique est présentée ci-dessous et s'exécute en 7,0 secondes. Elle renvoie la bonne réponse. J'ai besoin de compter les lignes en fonction de certaines conditions, puis d'obtenir le nombre maximum. Mon problème est la performance de cette requête indépendante. Cette même requête enveloppée dans un curseur s'exécute en 0,15 seconde. Dans le curseur, le plan de requête est très différent. Comment puis-je faire en sorte que la requête autonome s'exécute plus rapidement ?
En utilisant des astuces, j'ai pu faire en sorte que le plan autonome ressemble au plan du curseur et cela a réglé le problème de vitesse.
Correction de la requête : (pas entièrement corrigée car l'OPTION échoue)
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [docSVenum1] with (nolock)
INNER LOOP JOIN [FTSindexWordOnce] as w1 with (NOLOCK, FORCESEEK)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER HASH JOIN [FTSindexWordOnce] as w2 with (NOLOCK)
ON w1.wordID = w2.wordID and w2.[sID] = '2'
GROUP BY W1.[sID]
-- OPTION (HASH GROUP)
) as list;
demande de problèmes :
select getdate();
go
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [FTSindexWordOnce] as w1 with (nolock)
INNER JOIN [docSVenum1] with (nolock)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER JOIN [FTSindexWordOnce] as w2 with (nolock)
ON w1.wordID = w2.wordID AND w2.[sID] = '2'
GROUP BY W1.[sID]
) as list;
go
select getdate(); -- 7.0 seconds
J'ai également besoin d'exécuter cette requête unique sur plusieurs valeurs et de la placer dans un curseur avec une boucle. Je sais que le curseur n'est pas une bonne solution, mais je n'ai pas réussi à trouver comment le faire sans curseur.
La requête seule et celle à l'intérieur de la boucle renvoient toutes deux la même réponse correcte.
Ma surprise est que la même requête dans une boucle de curseur est 40 fois plus rapide.
DECLARE @sid int
DECLARE sID_cursor CURSOR FOR
SELECT top 80 sID
FROM docSVsys
WHERE sID = '2' -- actually I want to not have this and let it loop through all
-- when i built the loop i saw performance improvement
ORDER BY sID
OPEN sID_cursor
FETCH NEXT FROM sID_cursor
INTO @sID
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @sID
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [FTSindexWordOnce] as w1 with (nolock)
INNER JOIN [docSVenum1] with (nolock)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER JOIN [FTSindexWordOnce] as w2 with (nolock)
ON w1.wordID = w2.wordID AND w2.[sID] = @sID
GROUP BY W1.[sID]
) as list
FETCH NEXT FROM sID_cursor
INTO @sID
END
CLOSE sID_cursor;
DEALLOCATE sID_cursor;
go
select getdate(); -- 0.15 seconds