访问sp_过程时应使用master.dbo吗?

时间:2019-06-26 14:15:28

标签: sql-server tsql sql-server-2016

我100%确信这是重复的,但是经过一个多小时的搜索,我似乎找不到答案。

在使用特殊过程(例如sp_之类的sp_executesql)时,明智的做法是使用完整的三部分标识符master.dbo(或master..)或仅使用按原样使用它们?我正在寻找性能最佳的版本:

1. sp_executesql
2. master..sp_executesql
3. master.dbo.sp_executesql

在性能方面,第2个和第3个在上述方面是完全相同的(例如,引用master),对于用户master..是安全的还是您不应该冒险使用master,因为某人仍然可以在某个位置创建另一个架构?

非常感谢。

1 个答案:

答案 0 :(得分:3)

TL; DR;
不应有明显的性能差异。

长话:
每当执行以sp_前缀开头的存储过程时,SQL Server都会首先在master.dbo中进行搜索,因此所有这三个选项应具有相同的性能。

摘自Eric Cobb在2015年发表的题为Why you should not prefix your stored procedures with “sp_”的文章

  

每当SQL Server在存储过程的开头看到“ sp_”时,它都会首先尝试在master数据库中查找该过程。如上面的Microsoft文档所述,“ SQL Server使用此前缀来指定系统过程”,因此,当SQL Server看到“ sp_”时,它将开始寻找系统过程。只有在它搜索完master数据库中的所有过程并确定您的过程不存在之后,它才会返回到数据库以尝试查找存储过程。

此外,它还引用了另一个官方文档(带有指向2008年版本的链接,用于查找当前版本):

  

用户定义的存储过程与系统存储过程同名,并且不合格或处于dbo模式中,将永远不会执行;系统存储过程将始终执行。

即使我在当前版本的文档中找不到该报价,也可以轻松证明。
考虑以下脚本:

USE <YourDatabaseNameHere> -- change to the actual name of the db, of course
GO

CREATE PROCEDURE dbo.sp_who
AS
    SELECT 'Zohar peled' as myName
GO

-- change to the actual name of the db, of course
EXEC <YourDatabaseNameHere>.dbo.sp_who
EXEC dbo.sp_who
EXEC sp_who

GO

DROP PROCEDURE  dbo.sp_who  -- cleanup

在2016版(这是我可用于测试的服务器)上进行测试时, 所有三个exec语句都执行了系统过程。我找不到任何执行程序的方法。

现在我无法在服务器上摆弄master数据库,因此我只能证明它对现有系统过程是正确的,但我很确定它是对于以sp_开头的任何过程,它都是相同的,即使您自己将其写到master数据库还是您自己的数据库,正如Aaron Bertrand在his article上标题为的插图所示另一个副作用:歧义

但是,即使不是这种情况,除非当前架构中有许多过程,并且在紧密的循环中运行存储过程,否则我怀疑您会发现任何值得注意的性能差异。
稍后在同一篇文章中:

  

如前所述,以“ sp_”命名的过程执行起来会更慢。它可能并不总是引人注目,但它确实存在。连接到DatabaseA,跳到主数据库并扫描那里的每个存储过程,然后返回DatabaseA并执行该过程通常要比连接到DatabaseA并执行该过程花费更多的时间。

请注意,本段讨论的是执行具有sp_前缀的用户定义的存储过程的性能问题-因此,让我们暂时扭转一下该过程:

假定SQL Server将必须扫描当前架构中的所有存储过程,然后,如果找不到,请转到Master.Dbo并开始查找。
很容易看到模式中包含的过程越多,花费的时间也越长。但是-您是否注意到SQL Server需要多长时间才能找到它需要运行的过程? 从2000版开始,我就一直在使用SQL Server,并且我的数据库共享了包含数百个全部存储在同一模式中的过程的数据库-但这从来不是性能问题。
实际上,在超过15年的SQL Server经验中,我从未遇到过因SQL Server查找需要运行的存储过程而导致的性能问题。