web-dev-qa-db-fra.com

Mesure des performances des requêtes: "Coût des requêtes du plan d'exécution" vs "Temps nécessaire"

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:

  1. Existe-t-il une source définitive pour expliquer ce que signifie cette mesure?

  2. 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 :)

48
MatBailie

La trace du profileur la met en perspective.

  • Requête A: 1,3 s CPU, 1,4 s durée
  • Requête B: 2,3 secondes CPU, durée 1,2 secondes

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 ...

34
gbn
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.
12
Aditya Acharya

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.

5
Quassnoi

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.

4
NMK

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

enter image description here

Plan d'exécution

enter image description here

2
Lijo

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:

enter image description here

Pour optimiser le coût des requêtes:

Cliquez sur votre SQL Management Studio

enter image description here

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

enter image description here

1
atik sarker