Je compare deux requêtes dans SQL Server 2012. Le but est d'utiliser toutes les informations pertinentes disponibles à partir de l'optimiseur de requêtes lors du choix de la meilleure requête. Les deux requêtes produisent les mêmes résultats; le orderid maximum pour tous les clients.
L'effacement du pool de mémoire tampon a été effectué avant d'exécuter chaque requête avec FREEPROCCACHE et DROPCLEANBUFFERS
En utilisant les informations fournies ci-dessous, quelle requête est le meilleur choix?
-- Query 1 - return the maximum order id for a customer
SELECT orderid, custid
FROM Sales.Orders AS O1
WHERE orderid = (SELECT MAX(O2.orderid)
FROM Sales.Orders AS O2
WHERE O2.custid = O1.custid);
-- Query 2 - return the maximum order id for a customer
SELECT MAX(orderid), custid
FROM Sales.Orders AS O1
group by custid
order by custid
TEMPS STATISTIQUE
Requête 1 TEMPS STATISTIQUE: Temps CPU = 0 ms, temps écoulé = 24 ms
Requête 2 TEMPS STATISTIQUE: Temps CPU = 0 ms, temps écoulé = 23 ms
STATISTIQUES IO
Requête 1 STATISTIQUES IO: Table 'Commandes'. Nombre de balayages 1, lectures logiques 5, lectures physiques 2, lectures anticipées 0, lectures logiques 0, lob lectures physiques 0, lob lectures anticipées 0.
Requête 2 STATISTIQUES IO: Table 'Commandes'. Nombre de balayages 1, lectures logiques 4, lectures physiques 1, lectures anticipées 8, lob lectures logiques 0, lob physiques lectures 0, lob lectures anticipées lisent 0.
Plans d'exécution
SELECT propriétés Query 1
SELECT propriétés Requête 2
Conclusions:
Requête 1
- Coût par lot de 48%
- Lectures logiques 5
- Lectures physiques 2
- Lectures anticipées: 0
- Temps CPU: 0 ms
- Temps écoulé 24 ms
- Coût estimé du sous-arbre: 0,0050276
- CompileCPU: 2
- CompileMemory: 384
- CompileTime: 2
Requête 2
- Coût par lot 52%
- Lectures logiques 4
- Physcial lit 1
- Lectures anticipées: 8
- Temps CPU 0
- Temps écoulé 23 ms
- Estimation du coût du sous-arbre: 0,0054782
- CompileCPU: 0
- CompileMemory: 192
- CompileTime: 0
Personnellement, même si Query 2 a un coût par lot plus élevé selon le plan graphique, je pense que c'est plus efficace que Query 1. Cela parce que la requête 2 nécessite moins de lectures logiques, a un temps écoulé légèrement inférieur, les valeurs compilecpu, compilememory et compiletime sont inférieur. les lectures avec lecture anticipée sont 8 pour la requête 2 et 0 pour la requête 1.
Mise à jour 12:03
Définition d'index clusterisé
ALTER TABLE [Sales].[Orders] ADD CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED
(
[orderid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Index non clusterisé idx_nc_custid
CREATE NONCLUSTERED INDEX [idx_nc_custid] ON [Sales].[Orders]
(
[custid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO