sql >> Database >  >> RDS >> Sqlserver

Optimaliseren van SQL-query's door de sorteeroperator in het uitvoeringsplan te verwijderen

Eerst moet u controleren of de sortering daadwerkelijk een prestatieknelpunt is. De duur van de sortering hangt af van het aantal elementen dat moet worden gesorteerd, en het aantal winkels voor een bepaalde bovenliggende winkel is waarschijnlijk klein. (Dat veronderstelt dat de sort-operator wordt toegepast na het toepassen van de waar-clausule).

Dat is een overgeneralisatie. Vaak kan een sorteeroperator triviaal naar de index worden verplaatst en, als alleen de eerste paar rijen van de resultatenset worden opgehaald, de querykosten aanzienlijk kunnen verlagen, omdat de database niet langer alle overeenkomende rijen hoeft op te halen (en ze te sorteren). all) om de eerste te vinden, maar kan de records in de volgorde van de resultatenset lezen en stoppen zodra er voldoende records zijn gevonden.

In jouw geval lijkt het alsof je de hele resultatenset ophaalt, dus sorteren zal de zaken waarschijnlijk niet veel erger maken (tenzij de resultatenset enorm is). Ook is het in jouw geval misschien niet triviaal om een ​​bruikbare gesorteerde index te maken, omdat de where-clausule een of bevat.

Als je nog steeds van die sort-operator af wilt, kun je het volgende proberen:

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

U kunt ook de volgende index proberen:

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

om te proberen de query-optimizer een scan van het indexbereik te laten uitvoeren op ParentStoreId alleen, scan vervolgens alle overeenkomende rijen in de index en voer ze uit als Type wedstrijden. Dit zal echter waarschijnlijk meer schijf-I/O veroorzaken, en daarom uw zoekopdracht vertragen in plaats van versnellen.

Bewerken :Als laatste redmiddel kunt u gebruik maken van

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]

met

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

en sorteer de twee lijsten op de applicatieserver, waar u de voorgesorteerde lijsten kunt samenvoegen (zoals in merge sort) en zo een volledige sortering vermijden. Maar dat is echt een micro-optimalisatie die, hoewel het sorteren zelf een orde van grootte versnelt, de totale uitvoeringstijd van de query waarschijnlijk niet veel zal beïnvloeden, omdat ik zou verwachten dat het knelpunt netwerk- en schijf-I/O zou zijn, vooral in het licht van het feit dat de schijf veel willekeurige toegang zal doen omdat de index niet geclusterd is.




  1. mysql selecteer tijdstempels tussen a en b retourneer alle of 0 tijdstempels

  2. MySQL aangepaste volgorde

  3. org.postgresql.util.PSQLException:FOUT:kolom user0_.id bestaat niet - Slaapstand

  4. MySQL relationele databases gebruiken op Fedora 12