반응형

SP는 최초(처음) 실행 하는 시점에 실행계획을 수립하고 이후에는 실행계획을 계속 재사용 하게 됩니다

(이것이 SP를 사용하는 중요한 이유 중 하나 입니다).

이 최초 실행계획 수립시, 인수로 넘겨진 파라미터(매개변수)를 기준으로 통계를 통해 예상 행수를 추측하게 됩니다.

그런데 넘겨진 파라미터가 아닌 로컬 변수를 이용해서 쿼리를 실행하면 옵티마이저가 행수 추측이 실패하게 되어

원하지 않는 실행 계획이 생성 될 수 있습니다.

이로 인하여 SP 성능이 저하 될 수 있습니다.

 

예를 들어 다음과 같이 SP 가 되어 있을 때,

create proc Proc1 (
@p_date varchar(8)
)
as
SELECT
   *
FROM 
   SDSaleMaster a
WHERE
   a.SaleDate = @p_date

SP를 호출 하면,

EXEC Proc1 @p_date = '20190601'

실행계획에서 행수를 1326으로 예측 합니다.

이는 통계와 일치하는 제대로 된 예상 행 수 이기 때문에, 실행계획이 적합하게 나올 가능성이 높습니다.

그런데 다음과 같이 매개변수가 아닌 로컬 변수를 사용 하게 되어 있을 때,

create proc proc1 (
@p_date varchar(8)
)
as
declare
   @v_date varchar(8)

set @v_date = convert(varchar(8), dateadd(d, -1, @p_date), 112)  -- 하루 전

SELECT
   *
FROM 
   SDSaleMaster a
WHERE
   a.SaleDate = @v_date

SP를 호출 하면,

 EXEC Proc1 @p_date = '20190602'

옵티마이저가 예상 행수를 제대로 추정할 수가 없어서 549로 나오는 데, 이는 해당 테이블의 평균 밀도값을 이용한 것 입니다.

평균밀도

예상 행수 = 밀도 * 테이블 전체 row 수

 

이 글이 도움이 되셨으면 좋아요 눌러 주시거나 댓글을 남겨 주세요.

반응형
반응형

① 저장 프로시저(이하 SP) 존재 여부 검사

  IF EXISTS (SELECT * FROM sysobjects WHERE id=object_id('SP명') AND objectproperty(id, 'IsProcedure')=1) ...


② SP가 배치(batch)의 첫번째 문장에서 실행된다면 EXECUTE 는 필요하지 않다.


③ SP 정의시 body는 BEGIN END 로 묶지 않아도 된다. 그냥 AS 뒤에 T-SQL이 오면 된다(사용자 함수 정의와 차이점 이다. 함수는 BEGIN END 사이에 정의 되어야 한다).


④ SP가 정보를 되돌릴 수 있는 방법은 3가지 이다.

  1. ResultSet (SELECT 문장 또는 다른 SP 호출로 가능)

  2. OUTPUT 파라미터

  3. 리턴값


  리턴값은 정수만 가능 하다. 리턴값이 설정되어 있지 않고 그냥 RETURN 만 하는 경우 기본값인 0을 되돌려 준다.

  SP호출시 리턴값은 다음과 같은 식으로 전달 받을 수 있다.

   

  DECLARE @intRet INT

  EXECUTE @intRet = Proc1 Pram1


⑤ SP에 매개변수값을 넘기는 방법에는 위치 매개변수 전달과 이름 매개변수 전달 방법이 있다.

    전자의 경우 SP에서 정의된 파라미터의 순서와 일치하게 넘기는 것이고 후자의 경우 @를 포함한 파라미터이름을 지정하여 넘기는 것이다.

    이름 매개변수 전달은 다음과 같은 식으로 한다.


   EXEC Proc1 @Param1 = 100, @Param2 = 'FOO'


⑥ SP 재컴파일

  때때로 Index 생성등을 통해 실행계획이 변경될 것을 예상 했으나 기존의 실행계획을 계속 유지하는 경우가 있다. 이럴 때는 SP를 재컴파일 해주면 새로운 실행계획이 반영될 수 있다.

특정 SP를 재컴파일 하기 위해서는 다음과 같이 한다.

  

  EXEC sp_recompile SP명


그런데 SP의 매개변수 값에 따라 데이터 분포도가 차이가 많이 나는 경우 하나의 실행계획으로만 처리되면 성능이 나오지 않는 경우가 있다. 이때는 다음과 같이 WITH RECOMPILE 옵션을 이용해서 SP를 정의하면 SP가 호출 될 때마다 매번 실행계획을 다시 수립하여 성능이 향상 될 수 있다.


CREATE PROC SP명

WITH RECOMPILE

AS


⑦ SP명 바꾸기

  ALTER PROC 으로는 SP명을 변경할 수 없다. 이를 때 sp_rename 프로시저를 호출하여 SP명을 변경하면 된다.


  EXEC sp_rename SP명1, SP명2


⑧ SP 종속(의존) 객체 확인

  sp_depends 를 이용하면 특정 SP에서 사용하고 있는 테이블, 컬럼등의 객체정보를 확인 할 수 있다.

  

  EXEC sp_depends SP명


⑨ 긴 SP 내용 검색

  SP 소스코드는 syscomments 시스템 테이블에 기록되는데, SP 소스 크기가 8000바이트 이상인 경우 2개 이상의 row로 소스가 분할 해서 저장이 된다. 그래서 여러 문자를 AND 로 LIKE 검색 하는 경우 제대로 해당하는 SP를 찾지 못할 수 있다. 이럴 때 다음과 같이 하면 원하는 SP를 찾을 수 있다. 


SELECT a.name

FROM sysObjects a

    INNER JOIN (    

        SELECT 

            id , STUFF ((

                SELECT ',' + text

                FROM sysComments y

                WHERE y.id = x.id

                FOR XML PATH ('')

                ) , 1,1 , '') AS AllText

        FROM  syscomments x

        GROUP BY id

    ) b

    ON a.id = b.id

WHERE    

    a.xtype = 'P'

    AND b.AllText Like '%문자열1%'

    AND b.AllText Like '%문자열2%'


반응형

+ Recent posts