使用 sp_ 启动用户存储过程的名称仍然错误吗?

33 stored-procedures sql-server-2008-r2

我的一位同事在我们的 SQL Server 2008 R2 数据库中命名了一个存储过程sp_something。看到这里,我立刻想:“那是错的!” 并开始在我的书签中搜索这篇解释错误原因的在线文章,以便我可以向我的同事提供解释。

在文章(由Brian Moran撰写)中解释说,给存储过程一个sp_前缀会使 SQL Server 查看主数据库以获取编译计划。因为sp_sproc不驻留在那里,SQL Server 将重新编译该过程(并且需要一个排它编译锁,导致性能问题)。

文章中给出了以下示例以显示两个程序之间的区别:

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
Run Code Online (Sandbox Code Playgroud)

您运行它,然后打开 Profiler(添加存储过程 ->SP:CacheMiss事件)并再次运行存储过程。您应该会看到两个存储过程之间的区别:sp_Select1存储过程生成的SP:CacheMiss事件比Select1存储过程多一个(文章引用了SQL Server 7.0SQL Server 2000。

当我在我的 SQL Server 2008 R2 环境中运行该示例时,我SP:CacheMiss为两个过程(在 tempdb 和另一个测试数据库中)获得了相同数量的事件。

所以我想知道:

  • 我在执行示例时是否做错了什么?
  • sproc sp_something在较新版本的 SQL Server 中,“不命名用户”谚语仍然有效吗?
  • 如果是这样,是否有一个很好的例子来说明它在 SQL Server 2008 R2 中的有效性?

非常感谢您对此的看法!

编辑

我在 msdn for SQL Server 2008 R2 上找到了Creating Stored Procedures (Database Engine),它回答了我的第二个问题:

我们建议您不要创建任何使用 sp_ 作为前缀的存储过程。SQL Server 使用 sp_ 前缀来指定系统存储过程。您选择的名称可能会与某些未来的系统程序冲突。[...]

虽然没有提到使用前缀引起的性能问题sp_。我很想知道情况是否仍然如此,或者他们是否在 SQL Server 2000 之后修复了它。

Aar*_*and 32

这很容易测试自己。让我们创建两个非常简单的过程:

CREATE PROCEDURE dbo.sp_mystuff
AS
  SELECT 'x';
GO
CREATE PROCEDURE dbo.mystuff
AS
  SELECT 'x';
GO
Run Code Online (Sandbox Code Playgroud)

现在让我们构建一个包装器来多次执行它们,有和没有模式前缀:

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
Run Code Online (Sandbox Code Playgroud)

结果:

在此处输入图片说明

结论:

  • 使用 sp_ 前缀较慢
  • 省略架构前缀较慢

更重要的问题:为什么使用 sp_ 前缀?您的同事希望从这样做中获得什么?这不应该是关于您必须证明这更糟,而应该是关于他们为系统中的每个存储过程添加相同的三个字母前缀的理由。我看不到好处。

此外,我在以下博客文章中对该模式进行了一些相当广泛的测试:

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


mar*_*c_s 13

我们建议您不要创建任何使用 sp_ 作为前缀的存储过程。SQL Server 使用 sp_ 前缀来指定系统存储过程。您选择的名称可能会与某些未来的系统程序冲突。[...]

但是没有提到使用 sp_ 前缀引起的性能问题。我很想知道情况是否仍然如此,或者他们是否在 SQL Server 2000 之后修复了它。

正如 Martin Smith 的简单评论所示 - 是的,如果您有一个带有sp_前缀的存储过程- SQL Server 查询执行器将始终首先检查master数据库以查看是否存在具有该名称的存储过程(标记为系统存储过程)。

如果它存在,那么来自master数据库的系统存储过程总是占上风,并且会被执行而不是你自己的。

所以,是的-它依然存在:不使用sp_前缀。

  • 测试简单。`CREATE PROC dbo.sp_helptext AS SELECT 1` 然后尝试`EXEC dbo.sp_helptext` (6认同)