Vẫn còn sai để bắt đầu tên của một thủ tục được lưu trữ của người dùng với sp_?


33

Một trong những đồng nghiệp của tôi đã đặt tên một thủ tục được lưu trữ trong cơ sở dữ liệu SQL Server 2008 R2 của chúng tôi sp_something. Khi nhìn thấy điều này, tôi nghĩ ngay: "Đó là SAI!" và bắt đầu tìm kiếm dấu trang của tôi cho bài viết trực tuyến này giải thích tại sao nó sai, vì vậy tôi có thể cung cấp cho đồng nghiệp của mình một lời giải thích.

Trong bài viết (của Brian Moran ), người ta giải thích rằng việc cung cấp cho thủ tục được lưu trữ một tiền tố sp_ làm cho SQL Server xem xét cơ sở dữ liệu chính cho một kế hoạch được biên dịch. Vì sp_sprockhông nằm trong đó, SQL Server sẽ biên dịch lại thủ tục (và cần một khóa biên dịch độc quyền cho điều đó, gây ra các vấn đề về hiệu năng).

Ví dụ sau đây được đưa ra trong bài viết để chỉ ra sự khác biệt giữa hai thủ tục:

USE tempdb;
GO

CREATE PROCEDURE dbo.Select1 AS SELECT 1;
GO

CREATE PROCEDURE dbo.sp_Select1 AS SELECT 1;
GO

EXEC dbo.sp_Select1;
GO

EXEC dbo.Select1;
GO

Bạn chạy cái này, sau đó mở Profiler (thêm Thủ tục lưu trữ -> SP:CacheMisssự kiện) và chạy lại các thủ tục được lưu trữ. Bạn phải thấy sự khác biệt giữa hai thủ tục được lưu trữ: thủ tục sp_Select1được lưu trữ sẽ tạo ra một SP:CacheMisssự kiện nhiều hơn Select1thủ tục được lưu trữ (bài viết tham khảo SQL Server 7.0SQL Server 2000. )

Khi tôi chạy ví dụ trong môi trường SQL Server 2008 R2, tôi nhận được cùng một lượng SP:CacheMisssự kiện cho cả hai thủ tục (cả trong tempdb và trong cơ sở dữ liệu thử nghiệm khác).

Vì vậy, tôi tự hỏi:

  • Tôi có thể làm điều gì sai trong việc thực hiện ví dụ này không?
  • sproc sp_somethingAdagium ' không đặt tên người dùng vẫn còn hiệu lực trong các phiên bản SQL Server mới hơn phải không?
  • Nếu vậy, có một ví dụ hay cho thấy tính hợp lệ của nó trong SQL Server 2008 R2 không?

Cảm ơn rất nhiều cho những suy nghĩ của bạn về điều này!

CHỈNH SỬA

Tôi đã tìm thấy Tạo thủ tục lưu trữ (Công cụ cơ sở dữ liệu) trên msDN cho SQL Server 2008 R2, câu trả lời cho câu hỏi thứ hai của tôi:

Chúng tôi khuyên bạn không nên tạo bất kỳ thủ tục được lưu trữ nào bằng cách sử dụng sp_ làm tiền tố. SQL Server sử dụng tiền tố sp_ để chỉ định các thủ tục lưu trữ hệ thống. Tên bạn chọn có thể xung đột với một số thủ tục hệ thống trong tương lai. [...]

Không có gì được đề cập ở đó về các vấn đề hiệu suất gây ra bằng cách sử dụng sp_tiền tố mặc dù. Tôi muốn biết liệu đó vẫn là trường hợp hay họ đã sửa nó sau SQL Server 2000.


3
Tôi đã xem xét điều này trước đây và thấy một sự khác biệt hiệu suất không đáng kể mà tôi đã đặt ra để giải quyết các sp_phiên bản lớn hơn một chút (cần kiểm tra cả cơ sở dữ liệu chính và cơ sở dữ liệu vì nó ưu tiên hệ thống trong master-> procs trong người dùng DB -> không phải hệ thống procs in master)
Martin Smith

4
Bạn thấy lợi ích gì cho tiền tố một thủ tục được lưu trữ với sp_? Điều này cũng hữu ích như tiền tố một bảng với tbl. Tại sao phải làm chủ hệ thống tìm kiếm trước (ngay cả khi nó không đáng kể hoặc không có hiệu suất khác biệt) để cho phép bạn sử dụng quy ước đặt tên vô nghĩa này?
Aaron Bertrand

1
@AaronBertrand: thành thật mà nói, tôi thấy không có lợi ích trong việc tiền tố sprocs với sp_, chỉ có nhược điểm và tôi sẽ không bao giờ tự tiền tố chúng theo cách này. Nhưng tôi muốn tất cả những lý lẽ mà tôi có thể có được để thuyết phục đồng nghiệp của mình không làm điều đó.

1
Vâng, tbl là vô dụng, nhưng tôi vẫn thích sử dụng nó. Phải là OCD của tôi đá vào. Bây giờ ra khỏi bãi cỏ của tôi.
SQLRockstar

1
@Josien cũng vậy, đồng nghiệp của bạn nên đến với các đối số để làm cho một kế hoạch đặt tên phức tạp hơn. Để họ giải thích tại sao dbo.sp_Author_Renametốt hơn dbo.Author_Rename. Tôi không thể nghĩ về một điều duy nhất có ý nghĩa.
Aaron Bertrand

Câu trả lời:


31

Điều này là khá dễ dàng để kiểm tra chính mình. Hãy tạo hai thủ tục rất đơn giản:

CREATE PROCEDURE dbo.sp_mystuff
AS
  SELECT 'x';
GO
CREATE PROCEDURE dbo.mystuff
AS
  SELECT 'x';
GO

Bây giờ, hãy xây dựng một trình bao bọc thực thi chúng một số lần, có và không có tiền tố lược đồ:

CREATE PROCEDURE dbo.wrapper_sp1
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @i INT = 1;
    WHILE @i <= 1000
    BEGIN
      EXEC sp_mystuff;
      SET @i += 1;
    END
END
GO
CREATE PROCEDURE dbo.wrapper_1
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @i INT = 1;
    WHILE @i <= 1000
    BEGIN
      EXEC mystuff;
      SET @i += 1;
    END
END
GO
CREATE PROCEDURE dbo.wrapper_sp2
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @i INT = 1;
    WHILE @i <= 1000
    BEGIN
      EXEC dbo.sp_mystuff;
      SET @i += 1;
    END
END
GO
CREATE PROCEDURE dbo.wrapper_2
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @i INT = 1;
    WHILE @i <= 1000
    BEGIN
      EXEC dbo.mystuff;
      SET @i += 1;
    END
END
GO

Các kết quả:

nhập mô tả hình ảnh ở đây

Kết luận:

  • sử dụng tiền tố sp_ chậm hơn
  • để lại tiền tố lược đồ chậm hơn

Câu hỏi quan trọng hơn: tại sao bạn muốn sử dụng tiền tố sp_? Đồng nghiệp của bạn mong đợi gì để đạt được điều đó? Điều này không phải là về việc bạn phải chứng minh rằng điều này tồi tệ hơn, nên nói về việc họ biện minh cho việc thêm tiền tố ba chữ cái giống nhau vào mỗi thủ tục được lưu trữ trong hệ thống. Tôi không thấy lợi ích.

Ngoài ra tôi đã thực hiện một số thử nghiệm khá rộng rãi của mẫu này trong bài đăng trên blog sau:

http://www.sqlperformance.com/2012/10/t-sql-queries/sp_prefix


Lưu ý, những kết quả này có trên SQL Server 2012. Nhưng bạn có thể thực hiện các bài kiểm tra tương tự trong môi trường của mình.
Aaron Bertrand

1
"Những đồng nghiệp của bạn mong đợi gì để đạt được điều đó" xem thêm Ký hiệu Hungary . Về cơ bản, đó là một điều của thập niên 90 đối với hầu hết các phần. Ngoài ra, ở công việc trước đây của tôi, tiêu chuẩn là tiền tố cho mọi thủ tục được lưu trữ sp_để chúng có thể được phân biệt với những thứ khác và không có xung đột tên ... Tôi không biết vấn đề về hiệu năng này tồn tại với nó.
Earlz

Ví dụ tuyệt vời, cảm ơn Aaron. Tôi vẫn đang thử nghiệm nó trên 2008 R2 (và có thể đang thử nghiệm sai cách, vì 'dbo.wrapper_sp1' và 'dbo.wrapper_sp2' có vẻ nhanh hơn đáng kể so với hai cái kia ngay bây giờ).

12

Chúng tôi khuyên bạn không nên tạo bất kỳ thủ tục được lưu trữ nào bằng cách sử dụng sp_ làm tiền tố. SQL Server sử dụng tiền tố sp_ để chỉ định các thủ tục lưu trữ hệ thống. Tên bạn chọn có thể xung đột với một số thủ tục hệ thống trong tương lai. [...]

Không có gì được đề cập ở đó về các vấn đề hiệu suất gây ra bằng cách sử dụng tiền tố sp_. Tôi muốn biết liệu đó có còn là vấn đề hay họ đã sửa nó sau SQL Server 2000.

Như nhận xét đơn giản của Martin Smith cho thấy - có, nếu bạn có một thủ tục được lưu trữ với sp_tiền tố - người thực thi truy vấn SQL Server sẽ luôn kiểm tra mastercơ sở dữ liệu trước để xem liệu thủ tục được lưu trữ (được đánh dấu là thủ tục lưu trữ hệ thống) có tồn tại không.

Và nếu nó tồn tại, hệ thống được lưu trữ thủ tục từ mastercơ sở dữ liệu luôn chiếm ưu thế và sẽ được thực thi thay vì của riêng bạn.

Vì vậy, có - nó vẫn đứng: không sử dụng các sp_tiền tố.


5
Đơn giản để kiểm tra. CREATE PROC dbo.sp_helptext AS SELECT 1sau đó thửEXEC dbo.sp_helptext
Martin Smith

Cảm ơn câu trả lời của bạn, bổ sung rất hữu ích về sự phổ biến của mastersp.

2

Một thử nghiệm tốt hơn là viết một truy vấn yêu cầu tối ưu hóa hoàn toàn vì đó có khả năng phản ánh tốt hơn những gì mà bạn đang viết. Tôi gói các truy vấn sau trong một SP và lặp lại thử nghiệm của bạn và nhận được kết quả tương tự.

select * from Person.BusinessEntity b
inner join Person.BusinessEntityAddress ba on b.BusinessEntityID = ba.BusinessEntityID
inner join Person.Address a on ba.AddressID = a.AddressID

Tôi đã nhận được cùng một số lần bỏ lỡ bộ đệm và các sự kiện nhấn trong cả hai trường hợp và trong cả hai trường hợp, kế hoạch đã được thêm vào bộ đệm. Tôi cũng đã chạy cả hai procs nhiều lần và không có sự khác biệt nhất quán về thời gian CPU hoặc thời gian trôi qua được báo cáo bởi dm_exec_query_stats.

Một mối quan tâm khác là vì các procs "sp_" có thể được thực thi từ master nên bạn có thể nhận được một bản sao của Proc đã được chạy thành master thay vì DB mà bạn đang làm việc nhưng một bài kiểm tra nhanh sẽ cho thấy không phải vậy. Tuy nhiên, nếu Proc bị loại bỏ khỏi DB mà bạn đang làm việc và một bản sao tồn tại trong bản chính thì nó sẽ bị xử lý nếu đó là một phiên bản cũ. Nếu đây là một mối quan tâm, tôi sẽ không sử dụng "sp_" để đặt tên cho Proc.


Tìm thấy thú vị, cảm ơn! Tôi sẽ sử dụng ví dụ của bạn kết hợp với ví dụ của Aaron để chạy thêm một số bài kiểm tra.

1

Tôi tin rằng vấn đề phải làm khi bạn không chỉ định tên đối tượng đủ điều kiện. Vì vậy, "EXEC sp_s Something" sẽ kiểm tra master trước, nhưng "EXEC dbname.dbo.sp_s Something" sẽ không bao giờ đi đến master trước.

Bài học, nếu tôi nhớ lại, là luôn luôn sử dụng tên đủ điều kiện.


5
Đừng nghĩ rằng điều đó làm cho bất kỳ sự khác biệt. EXEC MyDB.dbo.sp_helptext 'sp_helptext'vẫn sử dụng một từ masterngay cả khi có một trong cơ sở dữ liệu người dùng. AFAIK nó kiểm tra cả hai vị trí và sẽ sử dụng một vị trí masternếu nó tồn tại và được đánh dấu là một đối tượng hệ thống.
Martin Smith

1
@MartinSmith vào năm 2012 Tôi không thể ép buộc phiên bản chính được thực thi (mặc dù các thử nghiệm của tôi đã cho thấy có điều gì đó đang diễn ra), trừ khi tôi bỏ bản sao cục bộ (trong trường hợp đó MyDB.dbo.sp_foovẫn thực hiện phiên bản chính). Tôi không có 2008/2008 R2 ngay bây giờ để xác nhận hành vi này đã thay đổi.
Aaron Bertrand

@AaronBertrand - Ah, thật thú vị, tôi đã làm bài kiểm tra của mình vào năm 2008 R2.
Martin Smith

Cũng lưu ý rằng nếu một thủ tục cục bộ không được tìm thấy và một thủ tục được tìm thấy trong master, thì cái sau sẽ được thực thi và không cần phải được đánh dấu là một đối tượng hệ thống để điều này xảy ra. Và trong năm 2012, ít nhất, dù bản sao chính có được đánh dấu là một đối tượng hệ thống hay không, không thay đổi hành vi - có hoặc không có tiền tố db / lược đồ cục bộ, bản sao cục bộ luôn được thực thi trừ khi nó không tồn tại.
Aaron Bertrand

1
Rất tiếc, tôi nên đã làm rõ rằng nhận xét của tôi là nhằm vào câu trả lời được đề xuất. Nhận xét của SQLRockstar "EXEC dbname.dbo.sp_s Something sẽ không bao giờ đi đến chủ trước." không chính xác
Greenstone Walker
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.