sql >> Database >  >> RDS >> Database

Prestatieverrassingen en veronderstellingen:STEL NOCOUNT IN OP

Als je ooit Management Studio hebt gebruikt, zal dit uitvoerbericht je waarschijnlijk bekend voorkomen:

(1 rij(en) aangetast)

Dit komt van SQL Server's DONE_IN_PROC bericht, dat wordt verzonden bij de succesvolle voltooiing van een SQL-instructie die een resultaat heeft opgeleverd (inclusief het ophalen van een uitvoeringsplan, daarom ziet u twee van deze berichten wanneer u eigenlijk maar één enkele query hebt uitgevoerd).

U kunt deze berichten onderdrukken met het volgende commando:

SET NOCOUNT ON;

Waarom zou je dat doen? Omdat deze berichten spraakzaam zijn en vaak nutteloos . In mijn Bad Habits en Best Practices-presentaties praat ik vaak over het toevoegen van SET NOCOUNT ON; op alle opgeslagen procedures en het inschakelen in applicatiecode die ad-hocquery's indient. (Tijdens het debuggen wil je misschien een vlag om de berichten weer aan te zetten, omdat de uitvoer in die gevallen nuttig kan zijn.)

Ik heb altijd de disclaimer toegevoegd dat het advies om deze optie overal aan te zetten niet universeel is; het hangt er van af. Old-school ADO-recordsets interpreteerden deze eigenlijk als resultatensets, dus als ze achteraf aan de query's worden toegevoegd, kunnen de toepassing(en) die ze al handmatig overslaan, worden verbroken. En sommige ORM's (hoest NHibernate hoest ) de resultaten daadwerkelijk ontleden om het succes van DML-opdrachten te bepalen (ugh!). Test uw wijzigingen.

Ik weet dat ik op een gegeven moment voor mezelf had bewezen dat deze spraakzame berichten de prestaties konden beïnvloeden, vooral via een traag netwerk. Maar het is lang geleden en vorige week vroeg Erin Stellato me of ik het ooit formeel had gedocumenteerd. Ik niet, dus hier komt het. We nemen een heel eenvoudige lus, waarbij we een tabelvariabele een miljoen keer bijwerken:

SET NOCOUNT OFF;
 
DECLARE @i INT = 1;
DECLARE @x TABLE(a INT);
INSERT @x(a) VALUES(1);
 
SELECT SYSDATETIME();
 
WHILE @i < 1000000
BEGIN
  UPDATE @x SET a = 1;
  SET @i += 1;
END
 
SELECT SYSDATETIME();

Een paar dingen die je misschien opvallen:

  • Het berichtenvenster wordt overspoeld met instanties van de (1 row(s) affected) bericht:

  • De initiële SELECT SYSDATETIME(); verschijnt pas in het resultatenvenster nadat de hele batch is voltooid. Dit komt door de overstromingen.
  • Het duurde ongeveer 21 seconden voordat deze batch werd uitgevoerd.

Laten we dit nu herhalen zonder de DONE_IN_PROC berichten, door SET NOCOUNT OFF; om SET NOCOUNT ON; en voer het opnieuw uit.

Hoewel het berichtenvenster niet langer vol stond met de betreffende rij(en) berichten, duurde het nog steeds ongeveer 21 seconden voordat de batch werd uitgevoerd.

Toen dacht ik, wacht even, ik weet wat er aan de hand is. Ik ben op een lokale computer, zonder netwerk, gebruik gedeeld geheugen, ik heb alleen SSD en klodders RAM...

Dus herhaalde ik de tests met mijn lokale exemplaar van SSMS tegen een externe Azure SQL Database - een Standard, S0, V12. Deze keer duurden de query's veel langer, zelfs nadat de iteraties waren teruggebracht van 1.000.000 naar 100.000. Maar nogmaals, er was geen tastbaar verschil in de uitvoering of DONE_IN_PROC berichten werden verzonden of niet. Beide batches duurden ongeveer 104 seconden, en dit was herhaalbaar over vele iteraties.

Conclusie

Jarenlang had ik de indruk gehad dat SET NOCOUNT ON; was een cruciaal onderdeel van elke prestatiestrategie. Dit was gebaseerd op observaties die ik had gedaan in, aantoonbaar, een ander tijdperk, en die zich vandaag minder zullen manifesteren.

Dat gezegd hebbende, zal ik SET NOCOUNT ON blijven gebruiken , zelfs als er op de hardware van vandaag geen merkbaar verschil in prestatie is. Ik ben nog steeds vrij sterk van het minimaliseren van netwerkverkeer waar mogelijk. Ik zou moeten overwegen een test uit te voeren waarbij ik veel meer beperkte bandbreedte heb (misschien heeft iemand een AOL-cd die ze me kunnen lenen?), of een machine heb waarvan de hoeveelheid geheugen lager is dan de uitvoerbufferlimieten van Management Studio, om er zeker van te zijn dat er is geen potentiële impact in de worstcasescenario's. In de tussentijd, hoewel het de waargenomen prestaties van uw toepassing misschien niet verandert, kan het uw portemonnee helpen om deze ingestelde optie altijd in te schakelen, vooral in situaties zoals Azure, waar u mogelijk moet betalen voor uitgaand verkeer.


  1. Postgres:selecteer de som van waarden en tel deze opnieuw op

  2. Query voor element van array in JSON-kolom

  3. mysql PDO hoe te binden LIKE

  4. SQLite SUM