J'ai créé la table big_table selon votre schéma
create table big_table
(
updatetime datetime not null,
name char(14) not null,
TheData float,
primary key(Name,updatetime)
)
J'ai ensuite rempli le tableau avec 50 000 lignes avec ce code:
DECLARE @ROWNUM as bigint = 1
WHILE(1=1)
BEGIN
set @rownum = @ROWNUM + 1
insert into big_table values(getdate(),'name' + cast(@rownum as CHAR), cast(@rownum as float))
if @ROWNUM > 50000
BREAK;
END
À l'aide de SSMS, j'ai ensuite testé les deux requêtes et réalisé que dans la première requête, vous recherchez le MAX de TheData et dans la seconde, le MAX de la mise à jour
J'ai donc modifié la première requête pour obtenir également le MAX de mise à jour
set statistics time on -- execution time
set statistics io on -- io stats (how many pages read, temp tables)
-- query 1
SELECT MAX([UpdateTime])
FROM big_table
-- query 2
SELECT MAX([UpdateTime]) AS value
from
(
SELECT [UpdateTime]
FROM big_table
group by [UpdateTime]
) as t
set statistics time off
set statistics io off
En utilisant Statistics Time, je récupère le nombre de millisecondes nécessaires pour analyser, compiler et exécuter chaque instruction
En utilisant Statistics IO, je récupère des informations sur l'activité du disque
STATISTICS TIME et STATISTICS IO fournissent des informations utiles. Tels que les tables temporaires utilisées (indiquées par la table de travail). Le nombre de pages logiques lues a également été lu, ce qui indique le nombre de pages de base de données lues dans le cache.
J'active ensuite le plan d'exécution avec CTRL + M (active afficher le plan d'exécution réel), puis j'exécute avec F5.
Cela fournira une comparaison des deux requêtes.
Voici la sortie de l' onglet Messages
- Requête 1
Table 'big_table'. Nombre de balayages 1, lectures logiques 543 , lectures physiques 0, lectures anticipées 0, lectures logiques 0, lob lectures physiques 0, lob lectures anticipées 0.
Temps d'exécution SQL Server:
temps CPU = 16 ms, temps écoulé = 6 ms .
- Requête 2
Table ' table de travail . Nombre de balayages 0, lectures logiques 0, lectures physiques 0, lectures anticipées 0, lectures logiques 0, lob lectures physiques 0, lob lectures anticipées 0.
Table 'big_table'. Nombre de balayages 1, lectures logiques 543 , lectures physiques 0, lectures anticipées 0, lectures logiques 0, lob lectures physiques 0, lob lectures anticipées 0.
Temps d'exécution SQL Server:
temps CPU = 0 ms, temps écoulé = 35 ms .
Les deux requêtes entraînent 543 lectures logiques, mais la deuxième requête a un temps écoulé de 35 ms alors que la première n'a que 6 ms. Vous remarquerez également que la deuxième requête entraîne l'utilisation de tables temporaires dans tempdb, indiquées par le mot table de travail . Même si toutes les valeurs de la table de travail sont à 0, le travail a toujours été effectué dans tempdb.
Ensuite, il y a la sortie de l' onglet Plan d'exécution réel à côté de l'onglet Messages
Selon le plan d'exécution fourni par MSSQL, la deuxième requête que vous avez fournie a un coût total par lot de 64% tandis que la première ne coûte que 36% du lot total, donc la première requête nécessite moins de travail.
À l'aide de SSMS, vous pouvez tester et comparer vos requêtes et savoir exactement comment MSSQL analyse vos requêtes et quels objets: tables, index et / ou statistiques, le cas échéant, sont utilisés pour satisfaire ces requêtes.
Une remarque supplémentaire à garder à l'esprit lors du test consiste à nettoyer le cache avant le test, si possible. Cela permet de garantir l'exactitude des comparaisons, ce qui est important lorsque vous pensez à l'activité du disque. Je commence par DBCC DROPCLEANBUFFERS et DBCC FREEPROCCACHE pour vider tout le cache. Attention cependant à ne pas utiliser ces commandes sur un serveur de production réellement utilisé car vous forcerez effectivement le serveur à tout lire du disque dans la mémoire.
Voici la documentation pertinente.
- Vider le cache du plan avec DBCC FREEPROCCACHE
- Effacez tout du pool de tampons avec DBCC DROPCLEANBUFFERS
L'utilisation de ces commandes peut ne pas être possible selon la façon dont votre environnement est utilisé.
Mis à jour 10/28 12:46 pm
Correction de l'image du plan d'exécution et de la sortie des statistiques.
getdate()
sortir de la boucle