Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Optimisation des requêtes SQL en supprimant l'opérateur de tri dans le plan d'exécution

Tout d'abord, vous devez vérifier que le tri est en fait un goulot d'étranglement des performances. La durée du tri dépendra du nombre d'éléments à trier, et le nombre de magasins pour un magasin parent particulier est susceptible d'être petit. (Cela suppose que l'opérateur de tri est appliqué après l'application de la clause where).

C'est une sur-généralisation. Souvent, un opérateur de tri peut être déplacé de manière triviale dans l'index et, si seules les deux premières lignes du jeu de résultats sont extraites, peut réduire considérablement le coût de la requête, car la base de données n'a plus besoin d'extraire toutes les lignes correspondantes (et de les trier tous) pour trouver les premiers, mais peut lire les enregistrements dans l'ordre du jeu de résultats et s'arrêter une fois que suffisamment d'enregistrements sont trouvés.

Dans votre cas, vous semblez récupérer l'intégralité de l'ensemble de résultats, il est donc peu probable que le tri empire les choses (à moins que l'ensemble de résultats ne soit énorme). De plus, dans votre cas, il peut ne pas être trivial de créer un index trié utile, car la clause where contient un or.

Maintenant, si vous voulez toujours vous débarrasser de cet opérateur de tri, vous pouvez essayer :

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

Vous pouvez également essayer l'index suivant :

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

pour essayer de faire en sorte que l'optimiseur de requête effectue une analyse de plage d'index sur ParentStoreId uniquement, puis analysez toutes les lignes correspondantes dans l'index, en les affichant si Type allumettes. Cependant, cela risque d'entraîner davantage d'E/S disque et donc de ralentir votre requête au lieu de l'accélérer.

Modifier :En dernier recours, vous pouvez utiliser

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]

avec

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

et triez les deux listes sur le serveur d'application, où vous pouvez fusionner (comme dans le tri par fusion) les listes pré-triées, évitant ainsi un tri complet. Mais c'est vraiment une micro-optimisation qui, tout en accélérant le tri lui-même d'un ordre de grandeur, est peu susceptible d'affecter beaucoup le temps d'exécution total de la requête, car je m'attendrais à ce que le goulot d'étranglement soit le réseau et les E/S de disque, surtout à la lumière du fait que le disque fera beaucoup d'accès aléatoires car l'index n'est pas groupé.