Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Nhận xét có thể cản trở hiệu suất thủ tục được lưu trữ không?

Thỉnh thoảng, một cuộc trò chuyện lại xuất hiện khi mọi người tin rằng nhận xét có tác động hoặc không có tác động đến hiệu suất.

Nói chung, tôi sẽ nói rằng, không, nhận xét không ảnh hưởng đến hiệu suất , nhưng luôn có chỗ cho tuyên bố từ chối trách nhiệm "nó phụ thuộc". Hãy tạo một cơ sở dữ liệu mẫu và một bảng đầy rác:

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

Bây giờ, tôi muốn tạo bốn thủ tục được lưu trữ - một thủ tục có 20 ký tự nhận xét, một có 2000 ký tự, một có 20.000 và một có 200.000. Và tôi muốn làm điều đó một lần nữa khi các nhận xét được nhúng * bên trong * một câu lệnh truy vấn trong thủ tục, trái ngược với việc độc lập (sẽ ảnh hưởng đến kế hoạch XML). Cuối cùng, tôi lặp lại quá trình thêm OPTION (RECOMPILE) vào truy vấn.

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;

Bây giờ, tôi cần tạo mã để chạy mỗi thủ tục 100.000 lần, đo thời lượng từ sys.dm_exec_procedure_stats và cũng kiểm tra kích thước của gói trong bộ nhớ 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;

Đầu tiên, hãy nhìn vào kích thước của các cơ quan thủ tục. Không có gì ngạc nhiên ở đây, chỉ cần xác nhận rằng mã xây dựng của tôi ở trên đã tạo ra kích thước mong đợi của các nhận xét trong mỗi quy trình:

Thủ tục Kích thước (byte)
Small_Separate / Small_Embedded 378
Medium_Separate / Medium_Embedded 4.340
Large_Separate / Large_Separate 40.338
ExtraLarge_Separate / ExtraLarge_Separate 400.348


Tiếp theo, dung lượng của các kế hoạch trong bộ nhớ cache là bao nhiêu?

Thủ tục Kích thước (byte)
Small_Separate / Small_Embedded 40.360
Medium_Separate / Medium_Embedded 40.360
Large_Separate / Large_Separate 40.360
ExtraLarge_Separate / ExtraLarge_Separate 40.360


Cuối cùng, màn trình diễn như thế nào? Không có OPTION (RECOMPILE) , đây là thời gian thực thi trung bình, tính bằng mili giây - khá nhất quán trên tất cả các quy trình:


Thời lượng trung bình (mili giây) - không có TÙY CHỌN (RECOMPILE)

Với OPTION (RECOMPILE) , chúng ta có thể thấy khoảng 50% lượt truy cập trong thời lượng trung bình trên toàn diện so với khi không biên dịch lại, nhưng vẫn khá đồng đều:


Thời lượng trung bình (mili giây) - với TÙY CHỌN (RECOMPILE)

Trong cả hai trường hợp, trong khi OPTION (RECOMPILE) phiên bản thường chạy chậm hơn, hầu như không có KHÔNG sự khác biệt trong thời gian chạy, bất kể kích thước nhận xét trong phần thân thủ tục.

Còn chi phí biên dịch cao hơn thì sao?

Tiếp theo, tôi muốn xem liệu những nhận xét lớn này có ảnh hưởng lớn đến chi phí biên dịch hay không, ví dụ:nếu các thủ tục được tạo WITH RECOMPILE . Mã xây dựng ở trên rất dễ thay đổi để giải thích cho điều này. Nhưng trong trường hợp này, tôi không thể dựa vào sys.dm_exec_procedure_stats , bởi vì điều này không hoạt động đối với các thủ tục WITH RECOMPILE . Vì vậy, mã tạo của tôi cho thử nghiệm hơi khác một chút, vì tôi phải theo dõi thời lượng trung bình theo cách thủ công:

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;

Trong trường hợp này, tôi không thể kiểm tra kích thước của các kế hoạch trong bộ nhớ cache, nhưng tôi có thể xác định thời gian chạy trung bình của các thủ tục và có sự khác biệt dựa trên kích thước nhận xét (hoặc, có lẽ chỉ là kích thước thân thủ tục):


Thời lượng trung bình (mili giây) - CÓ RECOMPILE ở cấp thủ tục

Nếu chúng ta đặt tất cả chúng lại với nhau trên một biểu đồ, rõ ràng WITH RECOMPILE đắt hơn bao nhiêu cách sử dụng có thể là:


Thời lượng trung bình (mili giây) - so sánh cả ba phương pháp

Tôi có thể sẽ xem xét kỹ hơn vấn đề này vào thời gian sau để biết chính xác vị trí mà cây gậy khúc côn cầu đó phát huy tác dụng - Tôi hình dung thử nghiệm với gia số 10.000 ký tự. Tuy nhiên, hiện tại, tôi khá hài lòng vì đã trả lời được câu hỏi.

Tóm tắt

Nhận xét dường như hoàn toàn không liên quan đến hiệu suất thủ tục được lưu trữ thực tế, có thể quan sát được, ngoại trừ trường hợp thủ tục được xác định WITH RECOMPILE . Cá nhân, tôi không thấy điều này được sử dụng trong tự nhiên nữa, nhưng YMMV. Để biết sự khác biệt nhỏ giữa tùy chọn này và OPTION (RECOMPILE) cấp câu lệnh , hãy xem bài viết của Paul White, "Đánh giá tham số, nhúng và các tùy chọn RECOMPILE.".

Cá nhân tôi nghĩ rằng các nhận xét có thể cực kỳ có giá trị đối với bất kỳ ai phải xem xét, bảo trì hoặc khắc phục sự cố mã của bạn. Điều này bao gồm cả bạn trong tương lai. Tôi thực sự khuyên bạn không nên lo lắng về tác động đến hiệu suất của một lượng nhận xét hợp lý mà thay vào đó, hãy tập trung vào việc ưu tiên mức độ hữu ích của ngữ cảnh mà các nhận xét đó cung cấp. Như ai đó trên Twitter đã nói, có một giới hạn. Nếu nhận xét của bạn tương đương với phiên bản rút gọn của Chiến tranh và Hòa bình, bạn có thể cân nhắc - có nguy cơ tách mã khỏi tài liệu của nó - đặt tài liệu đó ở nơi khác và tham khảo liên kết trong phần nhận xét của cơ quan thủ tục.

Để giảm thiểu rủi ro tách rời hoặc tài liệu và mã trở nên không đồng bộ theo thời gian, bạn có thể tạo quy trình thứ hai, với hậu tố _documentation hoặc _comments và đặt các nhận xét (hoặc một phiên bản đã nhận xét của mã) ở đó. Có thể đặt nó trong một lược đồ khác để ngăn nó ra khỏi danh sách sắp xếp chính. Ít nhất thì tài liệu vẫn ở với cơ sở dữ liệu ở bất cứ đâu, mặc dù nó không đảm bảo rằng nó sẽ được duy trì. Rất tiếc là không thể tạo quy trình bình thường WITH SCHEMABINDING , trong trường hợp đó, bạn có thể ràng buộc thủ tục nhận xét với nguồn.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. BẢNG SQL

  2. Ngôn ngữ Định nghĩa Dữ liệu SQL

  3. CHẾ ĐỘ XEM SQL

  4. Không gian bảng SYSMGMTDATA là ĐẦY ĐỦ trong Kho lưu trữ Quản lý Cơ sở Hạ tầng Lưới (MGMTDB)

  5. Kết nối với Teradata trong IRI Workbench