J'essaie de déterminer les performances relatives de deux requêtes différentes et j'ai deux façons de mesurer cela:
1. Exécutez les deux et chronométrez chaque requête
2. Exécutez les deux et obtenez "Coût de la requête" à partir du plan d'exécution réel
Voici le code que je lance 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 je reçois 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 temps d'exécution contredisent directement les résultats du coût de la requête, mais j'ai du mal à déterminer ce que signifie réellement le "coût de la requête". Ma meilleure supposition est que c'est un agrégat de lectures/écritures/CPU_Time/etc, donc je suppose que j'ai quelques questions:
Existe-t-il une source définitive pour expliquer ce que signifie cette mesure?
Quelles autres mesures de "performances des requêtes" les utilisateurs utilisent-ils et quels sont leurs avantages relatifs?
Il peut être important de noter qu'il s'agit d'un serveur SQL de taille moyenne, exécutant MS SQL Server 2005 sur MS Server 2003 Enterprise Edition avec plusieurs processeurs et plus de 100 utilisateurs simultanés.
MODIFIER:
Après quelques ennuis, j'ai réussi à obtenir un accès Profiler sur ce serveur SQL et je peux donner des informations supplémentaires (qui prend en charge le coût de la requête lié aux ressources système, 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 prendre plus de CPU avec BEAUCOUP plus de lectures prend moins de temps :)
La trace du profileur la met en perspective.
La requête B utilise le parallélisme: CPU> durée, par exemple, la requête utilise 2 CPU, en moyenne 1,15 s chacune
La requête A n'est probablement pas: CPU <durée
Cela explique le coût par rapport au lot: 17% du pour le plan de requête non parallèle plus simple.
L'optimiseur détermine que la requête B est plus coûteuse et bénéficiera du parallélisme, même si cela nécessite des efforts supplémentaires.
Rappelez-vous cependant que cette requête B utilise 100% de 2 CPUS (donc 50% pour 4 CPU) pendant environ une seconde. La requête A utilise 100% d'un seul processeur pendant 1,5 seconde.
Le pic de la requête A est plus faible, au détriment d'une durée accrue. Avec un seul utilisateur, qui s'en soucie? Avec 100, ça fait peut-être une différence ...
SET STATISTICS TIME ON
SELECT *
FROM Production.ProductCostHistory
WHERE StandardCost < 500.00;
SET STATISTICS TIME OFF;
Et voir l'onglet du 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 la requête, mais j'ai du mal à déterminer ce que signifie réellement le "coût de la requête".
Query cost
est ce que l'optimiseur pense du temps que prendra votre requête (par rapport au temps de traitement total).
L'optimiseur essaie de choisir le plan de requête optimal en examinant votre requête et les statistiques de vos données, en essayant plusieurs plans d'exécution et en sélectionnant le moins coûteux d'entre eux.
Ici vous pouvez lire plus en détail comment il essaie de faire cela.
Comme vous pouvez le voir, cela peut différer considérablement de ce que vous obtenez réellement.
La seule véritable métrique de performance des requêtes est, bien sûr, la durée réelle de la requête.
Utilisation SET STATISTICS TIME ON
au-dessus de votre requête.
Sous l'onglet de résultats proche, vous pouvez voir un onglet de message. Là, vous pouvez voir l'heure.
Je comprends que c'est une vieille question - mais je voudrais ajouter un exemple où le coût est le même mais une requête est meilleure que l'autre.
Comme vous l'avez observé dans la question,% affiché 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 effectuant la même tâche. Le 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 de nettes différences.
Dans l'exemple suivant, la requête 1 utilise seek
tandis que la requête 2 utilise scan
sur la table LWManifestOrderLineItems. Lorsque nous vérifions réellement le temps d'exécution, nous constatons cependant que Query 2 fonctionne mieux.
Lire aussi Quand une recherche n'est-elle pas une recherche? par 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
Temps d'exécution de la requête:
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]
Query Out Put sera comme:
Pour optimiser le coût des requêtes:
Cliquez sur votre SQL Management Studio
Exécutez votre requête et cliquez sur Plan d'exécution à côté de l'onglet Messages du résultat de votre requête. tu verras comme