Mesure de la Performance de la requête: coût de la requête "Plan D'exécution" par rapport au temps pris"
j'essaie de déterminer la performance relative de deux requêtes différentes et j'ai deux façons de mesurer ceci à ma disposition:
1. Exécutez les deux et chronométrez chaque requête
2. Exécuter les deux et obtenir "coût de requête" du plan d'exécution réelle
voici le code que j'exécute pour chronométrer les requêtes...
DBCC FREEPROCCACHE
GO
DBCC DROPCLEANBUFFERS
GO
DECLARE @start DATETIME SET @start = getDate()
EXEC test_1a
SELECT getDate() - @start AS Execution_Time
GO
DBCC FREEPROCCACHE
GO
DBCC DROPCLEANBUFFERS
GO
DECLARE @start DATETIME SET @start = getDate()
EXEC test_1b
SELECT getDate() - @start AS Execution_Time
GO
ce que j'obtiens est le suivant:
Stored_Proc Execution_Time Query Cost (Relative To Batch)
test_1a 1.673 seconds 17%
test_1b 1.033 seconds 83%
les résultats du le temps d'exécution contredit directement les résultats du coût de requête, mais j'ai de la difficulté à déterminer ce que "coût de requête" signifie réellement. Ma meilleure supposition est qu'il s'agit d'un agrégat de lit / écrit/ CPU_Time / etc, Donc je suppose que j'ai quelques questions:
-
Existe-t-il une source de définition pour expliquer ce que cette mesure signifie?
-
Ce que les autres "les Performances de la Requête" paramètres n'gens utilisent, et ce sont de leurs mérites?
Il peut être important de noter qu'il s'agit d'un serveur SQL de taille moyenne, qui exécute MS SQL Server 2005 sur MS Server 2003 Enterprise Edition avec plusieurs processeurs et plus de 100 utilisateurs concurrents.
EDIT:
après quelques soucis j'ai réussi à obtenir L'accès Profiler sur ce serveur SQL, et peut donner des informations supplémentaires (qui soutient le coût de requête étant lié au système Ressources, pas le temps d'exécution lui-même...)
Stored_Proc CPU Reads Writes Duration
test_1a 1313 3975 93 1386
test_1b 2297 49839 93 1207
Impressionnant que la prise de plus de CPU avec BEAUCOUP plus de Lectures prend moins de temps :)
6 réponses
le profileur trace le met en perspective.
- requête a: 1.3 sec CPU, 1.4 sec Durée "151930920 de la Requête" B: 2.3 secondes CPU, 1.2 secondes de durée
la requête B utilise le parallélisme: CPU > durée eg la requête utilise 2 CPU, moyenne 1,15 secondes chaque
requête a n'est probablement pas: CPU < duration
ce qui explique le coût relatif au lot: 17% du prix de la plan de requête simple et non parallèle.
l'optimiseur réalise que la requête B est plus chère et bénéficiera du parallélisme, même si cela demande un effort supplémentaire.
rappelez-vous cependant, que la requête B utilise 100% de 2 CPU (donc 50% pour 4 CPU) pour une seconde ou plus. La requête a utilise 100% D'un CPU simple pendant 1,5 secondes.
Le pic pour la requête A est inférieure, à la charge de l'accroissement de la durée. Avec un seul utilisateur, qui s'en soucie? Avec 100, peut-être que cela fait une différence...
SET STATISTICS TIME ON
SELECT *
FROM Production.ProductCostHistory
WHERE StandardCost < 500.00;
SET STATISTICS TIME OFF;
Et voir l'onglet message, il ressemblera à ceci:
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 10 ms.
(778 row(s) affected)
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
les résultats du temps d'exécution contredisent directement les résultats du coût de requête, mais j'ai de la difficulté à déterminer ce que" coût de requête " signifie réellement.
Query cost
est ce que optimizer pense de la durée de votre requête (par rapport à la durée totale du lot).
L'optimiseur tente de choisir le plan de requête optimal en regardant votre requête et les statistiques de vos données, en essayant plusieurs plans d'exécution et choisir le moins coûteux d'entre eux.
Ici , vous pouvez lire plus en détail sur la façon qu'il ne tente de le faire.
comme vous pouvez le voir, cela peut différer considérablement de ce que vous obtenez réellement.
la seule vraie métrique de performance de requête est, bien sûr, combien de temps la requête prend réellement.
Utiliser SET STATISTICS TIME ON
au-dessus de votre requête.
ci-dessous, près de l'onglet résultat, vous pouvez voir un onglet message. De là, vous pouvez voir l'heure.
je comprends que c'est une vieille question – je voudrais toutefois ajouter un exemple où le coût est le même, mais une requête est mieux que l'autre.
comme vous l'avez fait remarquer dans la question, le pourcentage indiqué dans le plan d'exécution n'est pas le seul critère pour déterminer la meilleure requête. Dans l'exemple suivant, j'ai deux requêtes à faire la même tâche. Plan d'exécution montre que les deux sont également bons (50% chacun). Maintenant j'ai exécuté les requêtes avec SET STATISTICS IO ON
qui montre des différences claires.
dans l'exemple suivant, la requête 1 utilise seek
tandis que la requête 2 utilise scan
sur la table LWManifestOrderLineItems. Quand nous vérifions réellement le temps d'exécution cependant il est de trouver que la requête 2 fonctionne mieux.
lire aussi quand une recherche n'est-elle pas une recherche? de Paul White
REQUÊTE
---Preparation---------------
-----------------------------
DBCC FREEPROCCACHE
GO
DBCC DROPCLEANBUFFERS
GO
SET STATISTICS IO ON --IO
SET STATISTICS TIME ON
--------Queries---------------
------------------------------
SELECT LW.Manifest,LW.OrderID,COUNT(DISTINCT LineItemID)
FROM LWManifestOrderLineItems LW
INNER JOIN ManifestContainers MC
ON MC.Manifest = LW.Manifest
GROUP BY LW.Manifest,LW.OrderID
ORDER BY COUNT(DISTINCT LineItemID) DESC
SELECT LW.Manifest,LW.OrderID,COUNT( LineItemID) LineCount
FROM LWManifestOrderLineItems LW
WHERE LW.Manifest IN (SELECT Manifest FROM ManifestContainers)
GROUP BY LW.Manifest,LW.OrderID
ORDER BY COUNT( LineItemID) DESC
statistiques IO
Plan D'Exécution
Exécution De La Requête Du Temps:
DECLARE @EndTime datetime
DECLARE @StartTime datetime
SELECT @StartTime=GETDATE()
` -- Write Your Query`
SELECT @EndTime=GETDATE()
--This will return execution time of your query
SELECT DATEDIFF(MILLISECOND,@StartTime,@EndTime) AS [Duration in millisecs]
Requête de Sortie Sera Comme:
Pour Optimiser Le Coût D'Interrogation:
cliquez sur votre Studio de gestion SQL
lancez votre requête et cliquez sur plan D'exécution à côté de L'onglet Messages de votre résultat de requête. vous verrez comme