Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Ottimizzazione delle query SQL rimuovendo l'operatore di ordinamento nel piano di esecuzione

Innanzitutto, dovresti verificare che l'ordinamento sia effettivamente un collo di bottiglia delle prestazioni. La durata dell'ordinamento dipenderà dal numero di elementi da ordinare ed è probabile che il numero di negozi per un particolare negozio principale sia piccolo. (Ciò presuppone che l'operatore di ordinamento venga applicato dopo aver applicato la clausola where).

Questa è una generalizzazione eccessiva. Spesso, un operatore di ordinamento può essere spostato banalmente nell'indice e, se vengono recuperate solo le prime due righe del set di risultati, può ridurre sostanzialmente il costo della query, perché il database non deve più recuperare tutte le righe corrispondenti (e ordinarle tutti) per trovare i primi, ma può leggere i record nell'ordine del set di risultati e fermarsi una volta trovati un numero sufficiente di record.

Nel tuo caso, sembra che tu stia recuperando l'intero set di risultati, quindi è improbabile che l'ordinamento peggiori le cose (a meno che il set di risultati non sia enorme). Inoltre, nel tuo caso potrebbe non essere banale costruire un utile indice ordinato, perché la clausola where contiene una o.

Ora, se vuoi ancora sbarazzarti di quell'operatore di ordinamento, puoi provare:

SELECT [Phone]
FROM [dbo].[Store]
WHERE [ParentStoreId] = 10
AND [Type] in (0, 1)
ORDER BY [Phone]    

In alternativa, puoi provare il seguente indice:

CREATE NONCLUSTERED INDEX IX_Store ON dbo.[Store]([ParentStoreId], [Phone], [Type])

per provare a fare in modo che Query Optimizer esegua una scansione dell'intervallo di indici su ParentStoreId solo, quindi scansiona tutte le righe corrispondenti nell'indice, emettendole se Type partite. Tuttavia, è probabile che ciò causi più I/O del disco e quindi rallenti la query anziché accelerarla.

Modifica :Come ultima risorsa, potresti usare

SELECT [Phone]
FROM [dbo].[Store]
WHERE [ParentStoreId] = 10
AND [Type] = 0
ORDER BY [Phone]

UNION ALL

SELECT [Phone]
FROM [dbo].[Store]
WHERE [ParentStoreId] = 10
AND [Type] = 1
ORDER BY [Phone]

con

CREATE NONCLUSTERED INDEX IX_Store ON dbo.[Store]([ParentStoreId], [Type], [Phone])

e ordinare i due elenchi sul server delle applicazioni, dove è possibile unire (come in merge sort) gli elenchi preordinati, evitando così un ordinamento completo. Ma questa è davvero una micro-ottimizzazione che, pur accelerando l'ordinamento stesso di un ordine di grandezza, è improbabile che influisca molto sul tempo di esecuzione totale della query, poiché mi aspetto che il collo di bottiglia sia l'I/O della rete e del disco, soprattutto alla luce del fatto che il disco eseguirà molti accessi casuali poiché l'indice non è raggruppato.