Sto confrontando due query in SQL Server 2012. L'obiettivo è utilizzare tutte le informazioni pertinenti disponibili da Query Optimizer quando si sceglie la query migliore. Entrambe le query producono gli stessi risultati; il massimo ordine per tutti i clienti.
La cancellazione del pool di buffer è stata eseguita prima di eseguire ogni query con FREEPROCCACHE e DROPCLEANBUFFERS
Utilizzando le informazioni fornite di seguito, quale query è la scelta migliore?
-- 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
TEMPO STATISTICO
TEMPO STATISTICO query 1: tempo CPU = 0 ms, tempo trascorso = 24 ms
TEMPO STATISTICO query 2: tempo CPU = 0 ms, tempo trascorso = 23 ms
STATISTICA IO
Query 1 STATISTICS IO: Tabella 'Ordini'. Conteggio scansioni 1, letture logiche 5, letture fisiche 2, letture avanti 0, letture logiche lob 0, letture fisiche lob 0, letture read lob 0.
Interrogazione 2 STATISTICS IO: Tabella 'Ordini'. Conteggio scansioni 1, letture logiche 4, letture fisiche 1, letture read-ahead 8, letture logiche lob 0, letture fisiche lob 0, letture read lob 0.
Piani di esecuzione
Proprietà SELECT SELEZIONE 1
Proprietà SELECT Query 2
conclusioni:
Query 1
- Costo del lotto 48%
- Letture logiche 5
- Letture fisiche 2
- Read-ahead Letture: 0
- Tempo CPU: 0ms
- Tempo trascorso 24ms
- Costo stimato della sottostruttura: 0,0050276
- CompileCPU: 2
- CompileMemory: 384
- CompileTime: 2
Query 2
- Costo del lotto 52%
- Letture logiche 4
- Letture fisiche 1
- Read-ahead Letture: 8
- Tempo CPU 0
- Tempo trascorso 23ms
- Costo stimato della sottostruttura: 0,0054782
- CompileCPU: 0
- CompileMemory: 192
- CompileTime: 0
Personalmente, anche se la Query 2 ha un costo batch più elevato secondo il piano grafico, penso che sia più efficace della Query 1. Questo perché la query 2 richiede meno letture logiche, ha un tempo trascorso leggermente inferiore, i valori compilecpu, compilememory e compiletime sono inferiore. le letture anticipate sono 8 per la query 2 e 0 per la query 1.
Aggiornamento 12:03
Definizione dell'indice cluster
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
Indice non cluster 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