Один из моих коллег назвал хранимую процедуру в нашей базе данных SQL Server 2008 R2 sp_something
. Когда я увидел это, я сразу подумал: «Это НЕПРАВИЛЬНО!» и начал поиск в моих закладках для этой онлайн-статьи, которая объясняет, почему это неправильно, поэтому я мог дать своему коллеге объяснение.
В статье ( Брайан Моран ) объясняется, что при присвоении хранимой процедуре префикса 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
Запустите его, затем откройте Profiler (добавьте SP:CacheMiss
событие «Хранимые процедуры ->» ) и снова запустите хранимые процедуры. Предполагается, что вы увидите разницу между двумя хранимыми процедурами: sp_Select1
хранимая процедура будет генерировать на одно SP:CacheMiss
событие больше, чем Select1
хранимая процедура (статья ссылается на SQL Server 7.0 и SQL Server 2000 ).
Когда я запускаю пример в своей среде SQL Server 2008 R2, я получаю одинаковое количество SP:CacheMiss
событий для обеих процедур (как в базе данных tempdb, так и в другой тестовой базе данных).
Вот мне и интересно
- Могу ли я сделать что-то не так при выполнении примера?
Является лиsproc sp_something
adagium «не называть пользователя » все еще действительным в более новых версиях SQL Server?- Если так, есть ли хороший пример, который показывает его действительность в SQL Server 2008 R2?
Большое спасибо за ваши мысли по этому поводу!
РЕДАКТИРОВАТЬ
Я нашел создание хранимых процедур (компонент Database Engine) в msdn для SQL Server 2008 R2, который отвечает на мой второй вопрос:
Мы рекомендуем вам не создавать хранимых процедур, используя sp_ в качестве префикса. SQL Server использует префикс sp_ для обозначения системных хранимых процедур. Выбранное вами имя может конфликтовать с какой-то будущей системной процедурой. [...]
Там ничего не сказано о проблемах производительности, вызванных использованием sp_
префикса. Я хотел бы знать, если это все еще так или они исправили это после SQL Server 2000.
sp_
версий (необходимо проверить как в основной, так и в пользовательской базах данных, поскольку это отдает приоритет системным процессам вmaster
-> процессам в пользовательской БД -> не системной Procs inmaster
)sp_
? Это примерно так же полезно, как префикс таблицы сtbl
. Зачем сначала использовать мастер поиска системы (даже если он незначителен или не имеет разницы в производительности), чтобы позволить вам использовать это бессмысленное соглашение об именах?dbo.sp_Author_Rename
это лучше, чемdbo.Author_Rename
. Я не могу думать об одной вещи, которая имеет смысл.Ответы:
Это довольно легко проверить самостоятельно. Давайте создадим две очень простые процедуры:
Теперь давайте создадим оболочку, которая выполняет их несколько раз, с префиксом схемы и без него:
Полученные результаты:
Выводы:
Более важный вопрос: почему вы хотите использовать префикс sp_? Что ваши коллеги ожидают получить от этого? Это не должно быть о том, что вам нужно доказывать, что это хуже, а о том, чтобы они оправдывали добавление одинакового трехбуквенного префикса к каждой хранимой процедуре в системе. Я не вижу выгоды.
Также я выполнил довольно обширное тестирование этого шаблона в следующем сообщении в блоге:
http://www.sqlperformance.com/2012/10/t-sql-queries/sp_prefix
источник
sp_
чтобы их можно было отличить от других вещей и не было конфликтов имен ... Я понятия не имел, что эта проблема с производительностью существует.Как показывает простой комментарий Мартина Смита - да, если у вас есть хранимая процедура с
sp_
префиксом - исполнитель запросов SQL Server всегдаmaster
сначала проверяет базу данных, чтобы узнать, существует ли хранимая процедура (помеченная как системная хранимая процедура) с таким именем.И если она существует, эта системная хранимая процедура из
master
базы данных всегда превалирует и будет выполняться вместо вашей.Так что да - это все еще стоит: не использовать в
sp_
приставку.источник
CREATE PROC dbo.sp_helptext AS SELECT 1
тогда попробуйEXEC dbo.sp_helptext
master
sp.Лучшим тестом является написание запроса, который требует полной оптимизации, поскольку это, вероятно, лучшее отражение того, что делает процесс, который вы пишете. Я завернул следующий запрос в SP и повторил ваш тест и получил те же результаты.
В обоих случаях я получил одинаковое количество событий пропуска и попадания в кэш, и в обоих случаях план был добавлен в кэш. Я также запускал оба процесса несколько раз, и не было постоянной разницы во времени ЦП или прошедшем времени, сообщаемом dm_exec_query_stats.
Другая проблема заключается в том, что, поскольку «sp_» -процедуры могут выполняться из master, вы можете получить копию proc, которая была запущена в master вместо базы данных, в которой вы работаете, но быстрый тест покажет, что это не так. Тем не менее, если процедура будет удалена из БД, в которой вы работаете, и копия будет существовать в master, то она будет выполнена, что может быть проблемой, если это старая версия. Если это проблема, я бы не использовал "sp_" в качестве имени процесса.
источник
Я считаю, что проблема связана с тем, что вы не указываете полное имя объекта. Таким образом, «EXEC sp_something» будет сначала проверять мастер, но «EXEC dbname.dbo.sp_something» никогда не будет идти сначала к мастеру.
Урок, если я помню, состоит в том, чтобы всегда использовать полностью определенное имя.
источник
EXEC MyDB.dbo.sp_helptext 'sp_helptext'
все еще использует тот из,master
даже если есть один в пользовательской базе данных. AFAIK проверяет оба местоположения и будет использовать одно из,master
если оно существует и помечено как системный объект.MyDB.dbo.sp_foo
все еще выполнялась основная версия). У меня нет 2008/2008 R2 прямо сейчас, чтобы подтвердить, где это поведение изменилось.