sql >> Database teknologi >  >> RDS >> Database

Kan kommentarer hæmme ydeevnen af ​​lagrede procedurer?

En gang i mellem dukker der en samtale op, hvor folk er overbevist om, at kommentarer enten har eller ikke har indflydelse på ydeevnen.

Generelt vil jeg sige, at nej, kommentarer påvirker ikke ydeevnen , men der er altid plads til en "det afhænger af" ansvarsfraskrivelse. Lad os oprette en prøvedatabase og en tabel fuld af junk:

CREATE DATABASE CommentTesting;
GO
USE CommentTesting;
GO
SELECT TOP (1000) n = NEWID(), * INTO dbo.SampleTable 
  FROM sys.all_columns ORDER BY NEWID();
GO
CREATE UNIQUE CLUSTERED INDEX x ON dbo.SampleTable(n);
GO

Nu vil jeg oprette fire lagrede procedurer - en med 20 tegn kommentarer, en med 2000, en med 20.000 og en med 200.000. Og det vil jeg gerne gøre igen, hvor kommentarerne er indlejret *indenfor* en forespørgselserklæring i proceduren, i modsætning til at være uafhængig (hvilket vil have en effekt på planens XML). Til sidst gentog jeg processen og tilføjede OPTION (RECOMPILE) til forespørgslen.

DECLARE @comments nvarchar(max) = N'', 
        @basesql  nvarchar(max),
        @sql      nvarchar(max);
 
SELECT TOP (5000) -- * 40 character strings
  @comments += N'--' + RTRIM(NEWID()) + CHAR(13) + CHAR(10)
FROM sys.all_columns;
 
SET @basesql = N'CREATE PROCEDURE dbo.$name$
AS
BEGIN
  SET NOCOUNT ON;
 
  /* $comments1$ */
 
  DECLARE @x int;
  SELECT @x = COUNT(*) /* $comments2$ */ FROM dbo.SampleTable OPTION (RECOMPILE);
END';
 
SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Small_Separate'),      N'$comments1$', LEFT(@comments, 20));
EXEC sys.sp_executesql @sql;
 
SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Medium_Separate'),     N'$comments1$', LEFT(@comments, 2000));
EXEC sys.sp_executesql @sql;
 
SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Large_Separate'),      N'$comments1$', LEFT(@comments, 20000));
EXEC sys.sp_executesql @sql;
 
SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'ExtraLarge_Separate'), N'$comments1$', LEFT(@comments, 200000));
EXEC sys.sp_executesql @sql;
 
SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Small_Embedded'),      N'$comments2$', LEFT(@comments, 20));
EXEC sys.sp_executesql @sql;
 
SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Medium_Embedded'),     N'$comments2$', LEFT(@comments, 2000));
EXEC sys.sp_executesql @sql;
 
SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'Large_Embedded'),      N'$comments2$', LEFT(@comments, 20000));
EXEC sys.sp_executesql @sql;
 
SET @sql = REPLACE(REPLACE(@basesql, N'$name$', N'ExtraLarge_Embedded'), N'$comments2$', LEFT(@comments, 200000));
EXEC sys.sp_executesql @sql;

Nu skulle jeg generere koden for at køre hver procedure 100.000 gange, måle varigheden fra sys.dm_exec_procedure_stats , og kontroller også størrelsen af ​​planen i cachen.

DECLARE @hammer nvarchar(max) = N'';
 
SELECT @hammer += N'
DBCC FREEPROCCACHE;
DBCC DROPCLEANBUFFERS;
GO
EXEC dbo.' + [name] + N';
GO 100000
 
SELECT [size of ' + [name] + ' (b)] = DATALENGTH(definition)
  FROM sys.sql_modules
  WHERE [object_id] = ' + CONVERT(varchar(32),([object_id])) + N';
 
SELECT [size of ' + [name] + ' (b)] = size_in_bytes
  FROM sys.dm_exec_cached_plans AS p
  CROSS APPLY sys.dm_exec_sql_text(p.plan_handle) AS t
  WHERE t.objectid = ' + CONVERT(varchar(32),([object_id])) + N';
 
SELECT N''' + [name] + N''', 
  avg_dur = total_elapsed_time*1.0/execution_count
  FROM sys.dm_exec_procedure_stats
  WHERE [object_id] = ' + CONVERT(varchar(32),([object_id])) + N';'
FROM sys.procedures
WHERE [name] LIKE N'%[_]Separate' OR [name] LIKE N'%[_]Embedded';
 
PRINT @hammer;

Lad os først se på størrelsen af ​​procedureorganerne. Ingen overraskelser her, det bekræfter bare, at min byggekode ovenfor genererede den forventede størrelse af kommentarer i hver procedure:

Procedure Størrelse (bytes)
Small_Separate / Small_Embedded 378
Medium_Separate / Medium_Embedded 4.340
Large_Separate / Large_Separate 40.338
ExtraLarge_Separate / ExtraLarge_Separate 400.348


Hvor store var dernæst planerne i cachen?

Procedure Størrelse (bytes)
Small_Separate / Small_Embedded 40.360
Medium_Separate / Medium_Embedded 40.360
Large_Separate / Large_Separate 40.360
ExtraLarge_Separate / ExtraLarge_Separate 40.360


Til sidst, hvordan var forestillingen? Uden OPTION (RECOMPILE) , her er den gennemsnitlige udførelsestid i millisekunder – ret konsistent på tværs af alle procedurer:


Gennemsnitlig varighed (millisekunder) – uden OPTION (RECOMPILE)

Med sætningsniveau OPTION (RECOMPILE) , kan vi se omkring 50 % hit i gennemsnitlig varighed over hele linjen sammenlignet med ingen genkompilering, men stadig ret jævnt:


Gennemsnitlig varighed (millisekunder) – med OPTION (RECOMPILE)

I begge tilfælde, mens OPTION (RECOMPILE) version kørte generelt langsommere, der var næsten NUL forskel i kørselstid, uanset kommentarstørrelse i procedureteksten.

Hvad med højere kompileringsomkostninger?

Dernæst ville jeg se, om disse store kommentarer ville have en enorm indvirkning på kompileringsomkostninger, for eksempel hvis procedurerne blev oprettet WITH RECOMPILE . Byggekoden ovenfor var let at ændre for at tage højde for dette. Men i dette tilfælde kunne jeg ikke stole på sys.dm_exec_procedure_stats , fordi dette ikke virker for procedurer WITH RECOMPILE . Så min generationskode til testen var lidt anderledes, da jeg skulle spore den gennemsnitlige varighed manuelt:

DECLARE @hammer nvarchar(max) = N'';
 
SELECT @hammer += N'
DBCC FREEPROCCACHE;
DBCC DROPCLEANBUFFERS;
SELECT SYSDATETIME();
GO
EXEC dbo.' + [name] + N';
GO 100000
SELECT SYSDATETIME();';
 
PRINT @hammer;

I dette tilfælde kunne jeg ikke kontrollere størrelsen af ​​planerne i cachen, men jeg var i stand til at bestemme den gennemsnitlige kørselstid af procedurerne, og der var en forskel baseret på kommentarstørrelsen (eller måske bare procedurens kropsstørrelse):


Gennemsnitlig varighed (millisekunder) – MED REKOMPILERING på procedureniveau

Hvis vi sætter dem alle sammen på en graf, er det tydeligt, hvor meget dyrere WITH RECOMPILE er. brug kan være:


Gennemsnitlig varighed (millisekunder) – sammenligning af alle tre metoder

Jeg vil nok se nærmere på dette på et senere tidspunkt for at se præcis, hvor den hockeystav kommer i spil – jeg forestiller mig at teste i trin på 10.000 tegn. For nu er jeg dog ret tilfreds med, at jeg har besvaret spørgsmålet.

Oversigt

Kommentarer ser ud til at være fuldstændig uden relation til faktisk, observerbar, lagret procedureydelse, undtagen i det tilfælde, hvor proceduren er defineret WITH RECOMPILE . Personligt ser jeg ikke, at dette bliver brugt i naturen længere, men YMMV. For de subtile forskelle mellem denne mulighed og OPTION (RECOMPILE) på sætningsniveau , se Paul Whites artikel, "Parameter Sniffing, Embedding, and the RECOMPILE Options."

Personligt tror jeg, at kommentarer kan være ekstremt værdifulde for alle, der skal gennemgå, vedligeholde eller fejlfinde din kode. Dette inkluderer fremtidige dig. Jeg anbefaler stærkt, at man ikke bekymrer sig om virkningen af ​​ydeevnen af ​​en rimelig mængde kommentarer, og i stedet fokuserer på at prioritere nytten af ​​kontekst, som kommentarerne giver. Som en på Twitter sagde, er der en grænse. Hvis dine kommentarer svarer til den forkortede version af Krig og Fred, kan du overveje – med risiko for at afkoble koden fra dens dokumentation – at placere denne dokumentation et andet sted og henvise til linket i procedureorganets kommentarer.

For at minimere risikoen for afkobling, eller at dokumentationen og koden på anden måde bliver ude af sync med tiden, kan du oprette en anden procedure med suffikset _documentation eller _comments , og placere kommentarerne (eller en kommenteret version af koden) der. Sæt det måske i et andet skema for at holde det ude af hovedsorteringslisterne. I det mindste forbliver dokumentationen med databasen, uanset hvor den går, selvom den ikke garanterer, at den vil blive vedligeholdt. Det er uheldigt, at en normal procedure ikke kan oprettes WITH SCHEMABINDING , i hvilket tilfælde du eksplicit kan knytte kommentarproceduren til kilden.


  1. MySQL opdaterer en sammenføjet tabel

  2. DBCA Opret database dårlig REMOTE_LISTENER

  3. Installation af WordPress 5 på ZEIT nu med MySQL Hosting

  4. En introduktion til asynkron behandling med Service Broker