sp_로 사용자 저장 프로 시저의 이름을 시작하는 것이 여전히 잘못 되었습니까?


33

동료 중 한 명이 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

이를 실행 한 다음 프로파일 러를 열고 (저장 프로 시저-> SP:CacheMiss이벤트 추가 ) 저장 프로 시저를 다시 실행하십시오. 두 저장 프로 시저의 차이점을 알아야합니다. sp_Select1저장 프로시 저는 저장 프로 시저 SP:CacheMiss보다 하나 이상의 이벤트 를 생성 Select1합니다 (이 기사는 SQL Server 7.0SQL Server 2000 참조 ).

SQL Server 2008 R2 환경에서 예제를 실행하면 SP:CacheMiss두 프로 시저 (tempdb 및 다른 테스트 데이터베이스 모두)에 대해 동일한 양의 이벤트 가 발생합니다.

그래서 궁금합니다.

  • 예제를 실행할 때 잘못된 일을 할 수 있습니까?
  • '사용자 이름을 지정하지 마십시오 sproc sp_something'adagium이 최신 버전의 SQL Server에서도 여전히 유효합니까?
  • 그렇다면 SQL Server 2008 R2의 유효성을 보여주는 좋은 예가 있습니까?

이것에 대한 당신의 생각에 감사드립니다!

편집하다

SQL Server 2008 R2의 msdn에서 저장 프로 시저 만들기 (데이터베이스 엔진) 를 찾았습니다 .

sp_를 접두사로 사용하여 저장 프로 시저를 만들지 않는 것이 좋습니다. SQL Server는 sp_ 접두사를 사용하여 시스템 저장 프로 시저를 지정합니다. 선택한 이름이 향후 시스템 절차와 충돌 할 수 있습니다. [...]

접두사 를 사용하여 발생하는 성능 문제 에 대해서는 언급되지 sp_않았습니다. 그래도 여전히 그렇거나 SQL Server 2000 이후에 수정했는지 알고 싶습니다.


3
나는 이것을 전에 보았고 무시할만한 성능 차이를 발견하여 sp_버전 을 해결하는 데 약간의 오버 헤드를 줄였습니다 (마스터 DB와 사용자 데이터베이스를 체크인해야 함 master-> 사용자 DB의 procs-> 비 시스템) procs in master)
Martin Smith

4
저장 프로 시저 앞에 접두사를 붙이면 어떤 이점이 sp_있습니까? 이것은 테이블에 접두사를 붙이는 것만 큼 유용합니다 tbl. 이 의미없는 명명 규칙을 사용할 수 있도록 시스템 검색 마스터를 먼저 만드는 이유는 무엇입니까?
Aaron Bertrand

1
@AaronBertrand : 솔직히 말해서, 난 더 이익을 볼 에 모두를 SP_ 만 단점으로 sprocs가 접두어에, 나는 이런 식으로 나 자신을 앞에하지 않을 것입니다. 하지만 동료들도 그렇게하지 말라고 설득 할 수있는 모든 주장을 원합니다.

1
예, tbl은 쓸모가 없지만 여전히 사용하는 것을 좋아합니다. 내 OCD가 시작되어야합니다. 이제 잔디밭에서 내리십시오.
SQLRockstar

1
@Josien은 또한 동료들 에게 이름 지정 체계를 더욱 복잡하게 만드는 주장 제기해야합니다 . 그들 dbo.sp_Author_Rename보다 더 나은 이유를 설명하게한다 dbo.Author_Rename. 말이되는 하나의 생각은 할 수 없습니다.
Aaron Bertrand

답변:


31

이것은 자신을 테스트하기가 매우 쉽습니다. 매우 간단한 두 가지 절차를 만들어 봅시다.

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

이제 스키마 접두사를 사용하거나 사용하지 않고 여러 번 실행하는 래퍼를 만들겠습니다

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

결과 :

여기에 이미지 설명을 입력하십시오

결론 :

  • sp_ 접두사를 사용하면 속도가 느려집니다
  • 스키마 접두사를 생략하면 속도가 느려집니다.

더 중요한 질문 : 왜 것입니다 원하는 SP_ 접두사를 사용할 수 있나요? 동료들은 그렇게함으로써 무엇 을 얻을 것으로 기대 합니까? 이것은 이것이 더 나쁘다는 것을 증명해야 할 필요가 없으며 시스템의 모든 단일 저장 프로 시저에 동일한 3 문자 접두사를 추가하는 것을 정당화해야합니다. 나는 이익을 보지 못한다.

또한 다음 블로그 게시물 에서이 패턴에 대해 꽤 광범위한 테스트를 수행했습니다.

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


이러한 결과는 SQL Server 2012에 대한 것입니다. 그러나 사용자 환경에서 동일한 테스트를 수행 할 수 있습니다.
Aaron Bertrand

1
"당신의 공동 작업은 그렇게함으로써 얻을 것으로 기대하는 것"도 헝가리 표기법을 참조하십시오 . 기본적으로 대부분 90 년대입니다. 또한 과거의 직업에서 표준은 모든 저장 프로 시저 앞에 sp_다른 것들과 구별되고 이름 충돌 이 없도록 모든 접두어를 접두어로 사용하는 것이 었습니다 ... 나는이 성능 문제가 존재한다는 것을 몰랐습니다.
Earlz

좋은 예, 아론 감사합니다. 나는 여전히 2008 R2에서 테스트 중입니다 (아마도 잘못된 방법으로 테스트하면 'dbo.wrapper_sp1'및 'dbo.wrapper_sp2'가 다른 두 개보다 훨씬 빠릅니다).

12

sp_를 접두사로 사용하여 저장 프로 시저를 만들지 않는 것이 좋습니다. SQL Server는 sp_ 접두사를 사용하여 시스템 저장 프로 시저를 지정합니다. 선택한 이름이 향후 시스템 절차와 충돌 할 수 있습니다. [...]

sp_ 접두사를 사용하여 발생하는 성능 문제에 대해서는 언급되지 않았습니다. 그래도 여전히 그렇거나 SQL Server 2000 이후에 문제가 해결되었는지 알고 싶습니다.

당신이 가진 저장 프로 시저가있는 경우 예, - 마틴 스미스의 간단한 코멘트에서 보듯이 sp_접두사를 -는 SQL Server 쿼리 실행자는 것입니다 항상 에 확인 master하는 이름 (시스템 저장 프로 시저로 표시) 저장 프로 시저가 존재하는지 확인하는 첫 번째 데이터베이스.

그리고 존재하는 경우 master데이터베이스의 해당 시스템 저장 프로 시저가 항상 우선하며 사용자 대신 실행됩니다.

그래서 그렇습니다-여전히 서 있습니다 . sp_접두사를 사용하지 마십시오 .


5
테스트가 간단합니다. CREATE PROC dbo.sp_helptext AS SELECT 1다음 시도EXEC dbo.sp_helptext
마틴 스미스

mastersp의 유병률에 대한 유용한 추가 답변을 주셔서 감사합니다 .

2

더 나은 테스트는 전체 최적화가 필요한 쿼리를 작성하는 것입니다. 작성중인 프로세스가 수행하는 작업을 더 잘 반영 할 수 있기 때문입니다. SP에 다음 쿼리를 래핑하고 테스트를 반복했으며 동일한 결과를 얻었습니다.

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

두 경우 모두 동일한 수의 캐시 미스 및 히트 이벤트가 발생했으며 두 경우 모두 계획이 캐시에 추가되었습니다. 또한 두 번의 procs를 여러 번 실행했으며 dm_exec_query_stats에서보고 한 CPU 시간 또는 경과 시간에 일관된 차이가 없었습니다.

다른 관심사는 "sp_"procs가 master에서 실행될 수 있기 때문에 작업중인 DB 대신 master로 실행 된 proc의 복사본을 얻을 수 있지만 빠른 테스트에서는 그렇지 않다는 것입니다. 그러나 작업중 인 DB에서 proc이 삭제되고 마스터에 사본이 있으면 이전 버전 인 경우 문제가 될 수 있습니다. 이것이 우려되는 경우 "sp_"를 사용하여 proc의 이름을 지정하지 않습니다.


재미있는 발견, 감사합니다! 더 많은 테스트를 실행하기 위해 예제Aaron 예제 와 함께 사용하겠습니다 .

1

정규화 된 개체 이름을 지정하지 않으면 문제가 해결되어야한다고 생각합니다. 따라서 "EXEC sp_something"은 먼저 마스터를 확인하지만 "EXEC dbname.dbo.sp_something"은 먼저 마스터로 이동하지 않습니다.

내가 기억한다면 교훈은 항상 완전한 이름을 사용하는 것입니다.


5
그것이 어떤 차이가 있다고 생각하지 마십시오. 사용자 데이터베이스에 EXEC MyDB.dbo.sp_helptext 'sp_helptext'하나가 master있더라도 여전히 하나를 사용합니다. AFAIK는 두 위치를 모두 확인하고 해당 위치 master가 존재하고 시스템 개체로 표시되어있는 위치를 사용 합니다.
Martin Smith

1
(내 시험이 있다는 것을 보여이 않았지만 2012 년 내가 실행되는 마스터 버전을 강요 할 수 없습니다 @MartinSmith 뭔가 내가 로컬 복사본을 감소하지 않는 한, 무슨) (이 경우 MyDB.dbo.sp_foo여전히 마스터 버전을 실행). 현재이 동작이 변경된 위치를 확인할 2008/2008 R2가 없습니다.
Aaron Bertrand

@AaronBertrand-아, 2008 R2에서 테스트를 해봤습니다.
Martin Smith

또한 로컬 프로 시저를 찾을 수없고 마스터에서 찾은 프로시 저는 후자가 실행되며이를 수행 하기 위해 시스템 오브젝트로 표시 할 필요 가 없습니다 . 그리고 2012 년에 최소한 마스터 사본이 시스템 오브젝트로 표시되는지 여부에 관계없이 로컬 db / 스키마 접두어가 있거나없는 동작은 변경되지 않습니다. 로컬 사본은 존재하지 않는 한 항상 실행됩니다.
Aaron Bertrand

1
죄송합니다. 내 의견이 제안 된 답변을 목표로하고 있음을 분명히해야합니다. SQLRockstar의 코멘트 "EXEC dbname.dbo.sp_something은 먼저 마스터로 이동하지 않습니다." 부정확하다.
그린 스톤 워커
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.