Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Bisakah komentar menghambat kinerja prosedur tersimpan?

Sesekali, percakapan muncul di mana orang-orang yakin bahwa komentar berpengaruh atau tidak berdampak pada kinerja.

Secara umum, saya akan mengatakan bahwa, tidak, komentar tidak memengaruhi kinerja , tetapi selalu ada ruang untuk penafian "itu tergantung". Mari kita buat database sampel dan tabel yang penuh dengan sampah:

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

Sekarang, saya ingin membuat empat prosedur tersimpan – satu dengan 20 karakter komentar, satu dengan 2000, satu dengan 20.000, dan satu dengan 200.000. Dan saya ingin melakukannya lagi di mana komentar disematkan * di dalam * pernyataan kueri dalam prosedur, sebagai lawan dari independen (yang akan berpengaruh pada paket XML). Akhirnya, saya mengulangi proses menambahkan OPTION (RECOMPILE) ke kueri.

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;

Sekarang, saya perlu membuat kode untuk menjalankan setiap prosedur 100.000 kali, mengukur durasi dari sys.dm_exec_procedure_stats , dan juga periksa ukuran paket di cache.

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;

Pertama, mari kita lihat ukuran badan prosedur. Tidak ada kejutan di sini, hanya mengonfirmasi bahwa kode konstruksi saya di atas menghasilkan ukuran komentar yang diharapkan di setiap prosedur:

Prosedur Ukuran (byte) Small_Separate / Small_Embedded 378 Media_Separate / Medium_Embedded 4.340 Terpisah_Besar / Terpisah_Besar 40.338 ExtraLarge_Separate / ExtraLarge_Separate 400.348


Selanjutnya, seberapa besar paket yang ada di cache?

Prosedur Ukuran (byte) Small_Separate / Small_Embedded 40.360 Media_Separate / Medium_Embedded 40.360 Terpisah_Besar / Terpisah_Besar 40.360 ExtraLarge_Separate / ExtraLarge_Separate 40.360


Akhirnya, seperti apa penampilannya? Tanpa OPTION (RECOMPILE) , berikut adalah waktu eksekusi rata-rata, dalam milidetik – cukup konsisten di semua prosedur:


Durasi rata-rata (milidetik) – tanpa OPSI (REKOMPILASI)

Dengan OPTION (RECOMPILE) tingkat pernyataan , kita dapat melihat sekitar 50% hit dalam durasi rata-rata di seluruh papan dibandingkan tanpa kompilasi ulang, tetapi masih cukup merata:


Durasi rata-rata (milidetik) – dengan OPTION (RECOMPILE)

Dalam kedua kasus, sementara OPTION (RECOMPILE) versi umumnya berjalan lebih lambat, hampir ada ZERO perbedaan runtime, terlepas dari ukuran komentar di badan prosedur.

Bagaimana dengan biaya kompilasi yang lebih tinggi?

Selanjutnya, saya ingin melihat apakah komentar besar ini akan berdampak besar pada biaya kompilasi, misalnya jika prosedur dibuat WITH RECOMPILE . Kode konstruksi di atas mudah diubah untuk memperhitungkan ini. Tapi dalam kasus ini, saya tidak bisa mengandalkan sys.dm_exec_procedure_stats , karena ini tidak berfungsi untuk prosedur WITH RECOMPILE . Jadi kode generasi saya untuk pengujian ini sedikit berbeda, karena saya harus melacak durasi rata-rata secara manual:

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;

Dalam hal ini, saya tidak dapat memeriksa ukuran paket dalam cache, tetapi saya dapat menentukan rata-rata runtime prosedur, dan ada perbedaan berdasarkan ukuran komentar (atau, mungkin, hanya ukuran tubuh prosedur):


Durasi rata-rata (milidetik) – DENGAN REKOMPILASI pada tingkat prosedur

Jika kita menggabungkan semuanya dalam sebuah grafik, jelas betapa lebih mahalnya WITH RECOMPILE penggunaan dapat:


Durasi rata-rata (milidetik) – membandingkan ketiga metode

Saya mungkin akan melihat ini lebih dekat di lain waktu untuk melihat dengan tepat di mana tongkat hoki itu berperan – saya membayangkan pengujian dalam peningkatan 10.000 karakter. Namun, untuk saat ini, saya cukup puas telah menjawab pertanyaan tersebut.

Ringkasan

Komentar tampaknya sama sekali tidak terkait dengan kinerja prosedur tersimpan yang sebenarnya dan dapat diamati, kecuali dalam kasus di mana prosedur didefinisikan WITH RECOMPILE . Secara pribadi, saya tidak melihat ini digunakan di alam liar lagi, tetapi YMMV. Untuk perbedaan halus antara opsi ini dan OPTION (RECOMPILE) tingkat pernyataan , lihat artikel Paul White, "Parameter Sniffing, Embedding, and the RECOMPILE Options."

Secara pribadi, saya pikir komentar bisa sangat berharga bagi siapa saja yang harus meninjau, memelihara, atau memecahkan masalah kode Anda. Ini termasuk masa depan Anda. Saya sangat menyarankan untuk tidak mengkhawatirkan dampak kinerja dari jumlah komentar yang masuk akal, dan alih-alih fokus pada memprioritaskan kegunaan konteks yang diberikan komentar. Seperti yang dikatakan seseorang di Twitter, ada batasnya. Jika komentar Anda merupakan versi singkat dari War and Peace, Anda dapat mempertimbangkan – dengan risiko memisahkan kode dari dokumentasinya – meletakkan dokumentasi itu di tempat lain, dan merujuk tautan di komentar badan prosedur.

Untuk meminimalkan risiko decoupling, atau dokumentasi dan kode menjadi tidak sinkron dari waktu ke waktu, Anda dapat membuat prosedur kedua, dengan akhiran _documentation atau _comments , dan meletakkan komentar (atau versi kode yang dikomentari) di sana. Mungkin memasukkannya ke dalam skema yang berbeda untuk menjauhkannya dari daftar sortir utama. Setidaknya dokumentasi tetap dengan database ke mana pun ia pergi, meskipun tidak menjamin itu akan dipertahankan. Sangat disayangkan bahwa prosedur normal tidak dapat dibuat WITH SCHEMABINDING , dalam hal ini Anda dapat secara eksplisit mengikat prosedur komentar ke sumbernya.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Prosesor AMD EPYC di Mesin Virtual Azure

  2. Hapus Posting dan Komentar dari Penjadwal Tindakan

  3. Ukuran Sampel dan Durasi STATISTIK PEMBARUAN:Apakah Penting?

  4. Memigrasikan Cluster Cassandra Anda

  5. Apakah awalan sp_ masih tidak-tidak?