다음 글에서 나온것처럼

http://dream6.tistory.com/entry/02-성능-스칼라-함수를-SELECT절이나-WHERE절에-썻을-경우-성능-저하


문제점

가뜩이나 스칼라함수는 WHERE절에 성능 문제가 있는데 암호화 함수까지 WHERE절에 넣어버리면 결과가 언제 나올지 가늠할수 없다..

select resoc_id
from t_n_mem
where 1=1
    AND resoc_id = '0000000011111111'
    AND master.dbo.dec_char_sel(0, 'SSN', SSN) = '9612250000001'

이와 같이 했을 경우 T_N_MEM 테이블의 레코드 개수만큼 암호화 함수가 실행된다.


해결 방법

암호화를 외부에서 해서 이후 값을 테이블과 비교해서 하던지 아니면 WITH문을 쓰던지 해야한다.

1. 외부에서 암호화를 해서 비교

select resoc_id
from t_n_mem
where 1=1
    AND resoc_id = '0000000011111111'
    AND SSN = 'XD01K3J43KLDJFDHHDOWEUOJUOEREOY'


2. WITH 문 사용

WITH T_ENCRYPT (SSN)
AS
(
                  SELECT master.dbo.dec_char_sel(0, 'SSN', '9612250000001') SSN
)
select resoc_id
from t_n_mem
where 1=1
    AND resoc_id = '0000000011111111'
    AND SSN = (SELECT SSN FROM T_ENCRYPT)







다음과 같은 쿼리가 있다

SELECT  resoc_id
FROM t_n_mem
WHERE 1 = 1
    
AND resoc_id = '0493019000940'
    AND mem_nm = '홍길동'
    and JOIN_MEM_DT = dbo.FN_GETDT(GETDATE())


위에 컬럼들에 인덱스가 잘 걸려있다고 가정해보자. 하지만 실제 실행 시간은 매우 오래 걸린다.

이유는 실제 SQL Server 실행 절차와 우리가 예상하는 실행 절차가 틀리기 때문이다.

우리가 예상하는 실행 절차

1. dbo.FN_GETDT는 날짜를 입력받아 YYYYMMDD 형태의 문자열을 리턴하는 함수이니
   현재 시간을 입력받아 1번 실행되어 문자열을 리턴

2. 리턴된 YYYYMMDD 문자열을 이용해 JOIN_MEM_DT 의 인덱스를 검색한다.


실제 실행 절차

1. FN_GETDT 는 스칼라 함수임을 알고 SQL 서버는 T_N_MEM의 레코드수만큼 FN_GETDT를 실행하고 

2. 이렇게 리턴받은 문자열을 매번 JOIN_MEM_DT와 비교한다.


이 차이는 스칼라 함수일 경우 100% 존재한다. 그렇기 때문에 WHERE절에 스칼라 함수를 쓰는것은 항상 피해야 한다. SELECT절에 넣는다면 WHERE절에서 걸려서 나온 ROW수만큼 실행되는것으로 그나마 괜찮은 성능을 보여주기도 하지만..


해결방법

1. 스칼라 함수를 확정적 함수로 바꾸어주면 될수도 있다. (가능성이 있다는 말이다. 항상 되지는 않음). 먼말인지는 조회좀 해보자. 안중요해서 패스

2. 테이블형태반환 함수로 바꾼다. 이 경우는 우리가 원하는 것만큼 딱 1번 실행된다.

SELECT  resoc_id
FROM t_n_mem
WHERE 1 = 1
    
AND resoc_id = '0493019000940'
    AND mem_nm = '홍길동'
    and JOIN_MEM_DT = (SELECT * FROM dbo.FN_GETDT(GETDATE()))




문제 증상

MSSQL varchar 로 된 컬럼을 자바가 사용시 db인덱스가 제대로 걸려 있어도 사용 못하는 문제

예제 쿼리

1
2
3
SELECT MEM_NM, SSN
FROM T_N_MEM
WHERE RESOC_ID = N'0394039008869'
cs


인덱스 상황

index_name       index_description                 index_keys 
---------------- --------------------------------- ----------

IX_CL_T_N_MEM_JT clustered located on FG_DATA1     JOIN_DTM   
IX_T_N_MEM_RI    nonclustered located on FG_INDEX1 RESOC_ID             


기반 지식

- 자바의 UTF-8은 MSSQL에서는 NVARCHAR 형식으로 구현된다. 약간 차이가 있지만
  이해를 위해 이래도 무방.

- 자바의 prepare sql 로 실행될때 입력 파라메터는 앞에 N을 붙여서 nvarchar 로
  들어온다.      N'apple'  <- 이렇게. 

- nvarchar이기 때문에 mssql에서 varchar로 되어 있는 컬럼과 비교시 성능문제가
  발생.


실행 계획

그림으로 보면 잘 안보인다.

아래 텍스트 실행 계획 보면 왜 느린지 바로 알수 있음.(일부만 발췌)

OBJECT:([NCMS].[dbo].[T_N_MEM].[IX_T_N_MEM_RI])

SEEK:([NCMS].[dbo].[T_N_MEM].[RESOC_ID] > [Expr1005] AND [NCMS].[dbo].[T_N_MEM].[RESOC_ID] < [Expr1006]),  

WHERE:(CONVERT_IMPLICIT(nvarchar(13),[NCMS].[dbo].[T_N_MEM].[RESOC_ID],0)=N'0394039008869') ORDERED


우리가 원하는 쿼리 실행과정

1. 유니코드 값 N'0394039008869' 으로 검색할때 암시적으로 이 값을 varchar로 변환

2. 테이블의 varchar 타입 컬럼과 같음(EQUAL) 비교를 하며 1개 값을 조회하는 포인트 쿼리로 실행


실제 실행되는 과정

1. 유니코드 값 N'0394039008869'  그대로 나둠
   varchar로 되어있는 컬럼의 모든 row들을 NVARCHAR로 암시적 변환 
   (위 TEXT 실행계획의 CONVERT_IMPLICIT 이 암시적 변환 하는 역할)

2. NVARCHAR로 암시적 변환된 컬럼들을 입력값 N'0394039008869'과 비교
   게다가 포인트검색(EQUAL 검색)도 아니고 범위검색(BETWEEN 검색)이 되어 버림


간단 요약

1. varchar 컬럼과 nvarchar 컬럼은 직접 비교가 불가능

2. varchar  -> nvarchar로 변환해서 비교하던지
   
nvarchar -> varchar로 변환해서 비교하던지 둘중하나

4. 입력 파라메터 nvarchar를 varchar로 변환해서 컬럼과 직접비교하면 Good인데

5. DB는 컬럼의 모든 row를 nvarchar로 변환한후 입력 파라메터(nvarchar)와 비교

   DB에 100만건이 있으면 100만건의 암시적 변환작업이 걸리기 때문이다.



해결책

SQL Server한테 맡기면 원하는대로 되지 않기에 아예 쿼리를 우리가 수동으로 변환 해주면 됨.


1
2
3
SELECT MEM_NM, SSN
FROM T_N_MEM
WHERE RESOC_ID = CAST(N'0394039008869' AS VARCHAR(50))
cs



OBJECT:([NCMS].[dbo].[T_N_MEM].[IX_T_N_MEM_RI]),
SEEK:([NCMS].[dbo].[T_N_MEM].[RESOC_ID]='0394039008869') ORDERED FORWARD

텍스트 버전으로 봐도 완벽하게 원하는 형태로 되었다.




--SET STATISTICS IO ON

--SET STATISTICS TIME ON



SELECT

                  PAGELIST.*,

                  DBO.GET_SUBJCLASSNM(PAGELIST.UPPERCLASS, '000') AS SUBJCLASSNM,

                  (CASE

                                   WHEN (SELECT

                                                                                        COUNT(*)

                                                                       FROM TZ_PROPOSE

                                                                       WHERE SUBJ = PAGELIST.SUBJ

                                                                       AND YEAR = PAGELIST.YEAR

                                                                       AND SUBJSEQ = PAGELIST.SUBJSEQ

                                                                       AND USERID = N'chojy314')

                                                     > 0 THEN 'Y'

                                   ELSE 'N'

                  END) AS PROPYN,

                  (CASE

                                   WHEN (SELECT

                                                                                        COUNT(*)

                                                                       FROM TZ_INTERESTSUBJ

                                                                       WHERE USERID = N'chojy314'

                                                                       AND SUBJ = PAGELIST.SUBJ)

                                                     > 0 THEN 'Y'

                                   ELSE 'N'

                  END) AS INTERESTSUBJ

FROM (SELECT

                                   ((TOTALPAGE + 1) - RNUM) AS TNUM,

                                   FLOOR((RNUM - 1) / 10 + 1) AS PAGENO,

                                   10 AS PAGESIZE,

                                   ORG_QUERY.*

                  FROM (SELECT

                                                     ROW_NUMBER() OVER (ORDER BY A.INDATE DESC) AS RNUM,

                                                     COUNT(*) OVER () AS TOTALPAGE,

                                                     A.SUBJ,

                                                     A.SUBJNM,

                                                     A.UPPERCLASS,

                                                     A.TUTOR,

                                                     A.EDUPERIOD,

                                                     A.CONTURL,

                                                     A.ISNEW,

                                                     A.ISHIT,

                                                     A.ISRECOM,

                                                     A.ISMOBILEYN,

                                                     A.INDATE,

                                                     A.EDULIMIT,

                                                     A.EDUTIMES,

                                                     A.ISMEMBERSHIP,

                                                     B.YEAR,

                                                     B.SUBJSEQ

                                   FROM TZ_SUBJ A

                                   INNER JOIN TZ_SUBJSEQ B

                                                     ON A.SUBJ = B.SUBJ

                                   WHERE 1 = 1

                                   AND B.GRCODE = 'N000003'

                                   AND B.YEAR = '0000'

                                   AND A.ISONOFF = 'N'

                                   AND A.ISUSE = 'Y'

                                   AND A.ISVISIBLE = 'Y'

                                   AND dbo.to_date(GETDATE(), 'yyyymmddHH24') BETWEEN B.EDUSTART AND B.EDUEND

                                   ORDER BY A.INDATE DESC OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY) ORG_QUERY) PAGELIST

WHERE 1 = 1

ORDER BY PAGELIST.RNUM

 


증상 : 이 쿼리를 실행하면 reads 는 13555 밖에 안되는데 4초이상 걸려버림. cpu도 4초이상.

      해당 쿼리를 개발에서 실행하면 또 빠름.


원인 : 개발과 운영의 실행시간이 다른것은 잘 모르겠으나 근본적인 문제가 있음.

위에 dbo.to_date(GETDATE(), 'yyyymmddHH24') 부분이 1번만 실행될줄 알았는데 resultset 갯수만큼 실행됨.


해결책 : 문제 부분을 tsql 변수로 처리해서 쿼리 윗부분에 변수 값 세팅하고 대체하는 방법


결과 : 0.1초 



SQL ServerCPU 및 메모리 자원을 많이 사용하는 시스템으로 전원 관리 옵션의 기본값인 균형 조정보다 고성능을 권장하고 있습니다.

적절하게 구성되어 있습니다.

 

Degraded overall performance on Windows Server 2008 R2

http://support.microsoft.com/kb/2207548


2) 백신 예외 영역 설정

현재는 백신이 설치되어 있지 않습니다만, 일반적으로 SQL Server 백신 예외 처리 항목 중에서 데이터 파일 및 로그 파일을 예외 처리가 가장 중요합니다.

적절한 구성이 필요합니다.

How to choose antivirus software to run on computers that are running SQL Server

http://support.microsoft.com/kb/309422/


일반적으로 SQL Server 서비스 계정에 필요한 필수 권한은 자동으로 부여되도록 구성되어 있으나, 메모리 페이지 잠금 권한과 볼륨 유지 관리 작업 수행 권한은 권장되는 권한입니다만 자동으로 부여되지 않습니다. 메모리 페이지 잠금은 버퍼풀 영역이 파일로 페이지아웃 되지 않도록 구성하여 안정적인 성능 유지에 도움이 되며, 볼륨 유지 관리 작업 수행 권한은 데이터 파일 즉시 초기화가 가능해 서버의 시작 또는 파일 자동 증가 시에 도움이 됩니다.

NARASARANG\sqlservice 계정에 권한 부여가 필요합니다.


4) MAX SERVER MEMORY 설정


5) MAX Degree of parallelism 설정

Max Degree of Parallelism 값은 하나의 쿼리가 수행될 때 사용하는 최대 CPU 개수를 지정하는 것인데요, 현재 시스템으로 볼 때 하나의 쿼리가 병렬로 처리될 때 모든 CPU를 사용할 필요가 없으므로 일반적으로 4정도로 제한할 것을 권장하고 있습니다.   CXPACKET(병렬처리를 위한 대기값) 엄청 나옴. SQL SERVER WAIT에서. 


7) 원격 관리자 연결 설정

REMOTE ADMIN CONNECTIONS 구성. SP_CONFIGURE에서 1로 설정

SQL SERVER 오류 로그 기본 갯수 6개인데. 30개정도로 늘려주자.

CPU 코어당 1개로 최대 8개까지. 크기와 증가량은 같은 크기로 설정.
http://yoonsy.tistory.com/31 <-- 여기가 진리

10) NVARCHARVARCHAR 형변환 성능 이슈

일반적으로WAS에서 JDBC를 통해 쿼리가 전달될 때 문자는 기본적으로 NVARCHAR 타입으로 바인딩 되게 됩니다. 만약 해당 테이블의 컬럼이 VARCHAR 타입일 경우 형변환이 발생하면서 인덱스를 제대로 타지 않는 등의 이슈가 발생할 가능성이 있습니다. Connection StringsendStringParametersAsUnicode=false 옵션 적용을 권장 드립니다. 자세한 사항은 아래 문서를 참조하세요.

http://technet.microsoft.com/ko-kr/library/ms378857(v=sql.105).aspx



MSSQL 2012 이전에는 셀프 조인 같은 방법을 써서 이전 방법을 찾는다.

하지만 2012에 LAG, LEAD 함수가 생겼다. 오라클과 이름과 기능 완전 동일

SQL Server 2012의 신규 함수로 LAG, LEAD 가 있습니다.

이미 오라클에서는 지원하고 있었지만, SQL Server 는 2012에 포함되었네요.

 

LAG 함수는 현재 결과집합에서 이전 행의 데이터를 가져오는 함수이고,

LEAD 함수는 LAG와 반대로 현재 결과집합에서 다음 행의 데이터를 가져오는 함수입니다.

 

이 함수가 나오기 이전에는 SELF JOIN을 사용하거나 CTE(Common Table Expression)을 사용해야 했습니다.

 

각설하고... SQL Server 2012의 샘플DB인 AdventureWoks2012 데이터베이스에서 예제를 만들어 보았습니다.

 

1. 원본 데이터 SELECT 

 

USE AdventureWorks2012

GO

 

SELECT

        ProductID, ModifiedDate, StandardCost

FROM

        Production.ProductCostHistory

WHERE

        ProductID IN (711, 712, 713)

ORDER BY

        ProductID, ModifiedDate

 

1.png

 

 

2. CTE 로 구현.

 

WITH LAG_LEAD_CTE

AS

(

        SELECT

               ROW_NUMBER() OVER (ORDER BY ProductID, ModifiedDate) AS RN, ProductID, ModifiedDate, StandardCost

        FROM

               Production.ProductCostHistory

        WHERE

               ProductID IN (711, 712, 713)

)

SELECT

        A.ProductID, A.StandardCost, A.ModifiedDate, B.StandardCost AS PrevStandardCost, C.StandardCost ASNextStandardCost

FROM

        LAG_LEAD_CTE A LEFT JOIN LAG_LEAD_CTE B ON A.ProductID = B.ProductID AND A.RN = B.RN + 1

        LEFT JOIN LAG_LEAD_CTE C ON A.ProductID = C.ProductID AND A.RN = C.RN - 1

ORDER BY

        A.ProductID, A.ModifiedDate

;

 

2-1.png

 ROW_NUMBER  를 주고 재귀쿼리를 이용,  뒤의 ROW, 앞의 ROW 와 조인하여  결과를 보여줍니다.

 

 

3. LAG / LEAD 함수를 사용하여 구현

 

SELECT

        ProductID, StandardCost, ModifiedDate,

        LAG(StandardCost, 1, NULL) OVER (PARTITION BY ProductID ORDER BY ModifiedDate) PrevStandardCost,

        LEAD(StandardCost, 1, NULL) OVER (PARTITION BY ProductID ORDER BY ModifiedDate) NextStandardCost

FROM

        Production.ProductCostHistory

WHERE

        ProductID IN (711, 712, 713)

ORDER BY ProductID, ModifiedDate

;

 

3-1.png

결과는 CTE와 LAG, LEAD 함수 사용 시 모두 같습니다만, 훨씬 구문이 가벼워진 것을 알 수 있습니다.

 

 

 

그럼 CTE로 구현했을 때와 LAG / LEAD 함수 로 구현했을 때의 성능 차이는 어느 정도일까요?

 

1) CTE 로 구현 시 IO 및 TIME 수치

 

SQL Server 구문 분석  컴파일 시간:

   CPU 시간 = 16ms, 경과 시간 = 25ms.

 

(9 행이 영향을 받음)

테이블 'Worktable'. 검색  0, 논리적 읽기  0, 물리적 읽기  0, 미리 읽기  0, LOB 논리적 읽기  0, LOB 물리적 읽기 0, LOB 미리 읽기  0.

테이블 'ProductCostHistory'. 검색  9, 논리적 읽기  18물리적 읽기  0, 미리 읽기  0, LOB 논리적 읽기  0, LOB 물리적 읽기  0, LOB 미리 읽기  0.

 

 SQL Server 실행 시간:

 CPU 시간 = 16밀리초경과 시간 = 4밀리초

 

 

2) LAG, LEAD 함수를 사용하여 구현 시 IO 및 TIME 수치

 

SQL Server 구문 분석  컴파일 시간:

   CPU 시간 = 11ms, 경과 시간 = 11ms.

 

(9 행이 영향을 받음)

테이블 'Worktable'. 검색  0, 논리적 읽기  0, 물리적 읽기  0, 미리 읽기  0, LOB 논리적 읽기  0, LOB 물리적 읽기 0, LOB 미리 읽기  0.

테이블 'ProductCostHistory'. 검색  3, 논리적 읽기  6물리적 읽기  0, 미리 읽기  0, LOB 논리적 읽기  0, LOB 물리적 읽기  0, LOB 미리 읽기  0.

 

 SQL Server 실행 시간:

 CPU 시간 = 0밀리초경과 시간 = 1밀리초

 

CTE보다 더 좋은 성능이 나오네요.


참고 URL : http://windtrap.tistory.com/95

테이블 

1. 인덱스 만들기
CREATE NONCLUSTERED INDEX IX_NC_T_N_MEM__MI_W2_I1 ON T_N_MEM (MEM_ID, MEM_NM, JOIN_DTM) INCLUDE (NICKNM)
ON [파일그룹명]
WITH (ONLINE=ON)  -- 엔터프라이즈 버전에서만

이름 규칙 IX_테이블명__첫번째컬럼약자_W(총컬럼갯수 -1)_I(인클루드컬럼갯수)


2. 인덱스 삭제
DROP INDEX IX_NC_T_N_MEM__MI_W2_I1 ON T_N_MEM


데이터베이스

1. 데이터파일 크기 증가
ALTER DATABASE webmail modify FILE ( NAME = N'WEBMAIL', SIZE = 280GB , FILEGROWTH = 3GB)


백업

1. LOG TRUNCATE (그냥 잘라내기) 
BACKUP log webmail to disk = N'NUL' WITH stats = 1  -- 1%단위로 경과보고

MSSQL 2012부터 WITH TRUNCATE_ONLY 옵션이 없어져서 가상의 NULL 디바이스에 백업하면 같은 효과 나옴

'MSSQL > 스크립트' 카테고리의 다른 글

bcp 사용방법  (0) 2010.12.03
SQL Server 2005 저장 프로시저 디버깅  (0) 2010.10.01

SQL Server 2014를 페일오버 클러스터링 환경 상태

다른 곳에서 복사해온 DB를 attach(연결) 했는데 읽기전용상태로 되는 현상이 발생


01. attach DB하기

USE [master]

GO

CREATE DATABASE [dbtest] ON

( FILENAME = N'J:\DBData\dbtest.mdf' ),

( FILENAME = N'L:\DBLog\dbtest_log.ldf' )

 FOR ATTACH

GO

02.  DB를 attach(연결)

     읽기전용상태로 되는 현상이 발생

      


03. 읽기전용 해제 시도

ALTER DATABASE DBTEST SET READ_WRITE      <- 이렇게 하면

다음과 같은 오류가 나온다.


메시지 5120, 수준 16, 상태 101, 줄 11

물리적 파일 "J:\DBData\DBTEST.mdf"을(를) 열 수 없습니다. 운영 체제 오류 5: "5(액세스가 거부되었습니다.)".

메시지 5120, 수준 16, 상태 101, 줄 11

물리적 파일 "L:\DBLog\DBTEST_log.ldf"을(를) 열 수 없습니다. 운영 체제 오류 5: "5(액세스가 거부되었습니다.)".

메시지 5181, 수준 16, 상태 5, 줄 11

데이터베이스 "dbtest"을(를) 다시 시작할 수 없습니다. 이전 상태로 돌아갑니다.

메시지 5069, 수준 16, 상태 1, 줄 11

ALTER DATABASE 문이 실패했습니다.


04. SQL Server 시작계정 확인


05. 문제점 & 해결 방법

OS 권한정책은 파일을 복사하면 그 해당 폴더의 권한을 상속받는것 같다.

그래서 SQL Server 시작계정이 그 파일에 쓰기권한이 없기 때문이다.

읽기전용 된 db를 detach 먼저하고 그 파일에 권한을 추가하면 될것이다.


그렇다면 어찌해야 하느냐? 두가지 방법을 생각해볼수 있다.


하나. SQL Server 시작계정이 mdf파일과 ldf파일에 읽고 쓰고 할수 있게 모든 권한을 준다

둘.  MSSQLSERVER 라는 내부 서비스 계정이 존재한다. 이 계정은 db create시 sql server 가 자동으로 이 계정을 mdf와 ldf에 모든 권한을 주게 되어있다.

위 두가지 방법 모두 절차는 같다.

나는는 좀더 어려운 두번째 방법을 설명한다.


mdf파일과 ldf파일에 모든 권한을 주는 방법을 따라해보자

   이 계정의 원래 이름은 'NT SERVICE\MSSQLSERVER' 이다.

   해당 파일을 오른쪽 클릭 / 속성 / 보안 / 편집 / 추가 하면 화면이 열린다.

   위치 버튼을 눌러 해당 컴퓨터로 하시고 다음과 같이 입력하고 이름 확인 버튼을 누른다.

   그럼 이름이 자동으로 MSSQLSERVER로 바뀐다. 확인 버튼 클릭
   권한 선택하는 화면이 나오는데 MSSQLSERVER 라는 계정에 모든권한을 선택하고          확인버튼 눌러 창을 닫음


이제 다시 ATTATCH하면 읽기전용 문제가 해결된 DB가 보일것이다.


다른 블로그에서 시작계정을 로컬시스템 계정으로 바꾸라고 하는곳도 있는데 그렇게 하면 administrator 권한을 가지는것이기에 당연 해결된다.

하지만 보안상 문제로 SQL Server 의 시작계정을 제한된 권한것으로 사용할 필요가 있을경우 이 절차에 따르면 될것이다.







1. 로컬파일로 내려받기(테이블 백업용도)
   a. 이진파일로 저장
     bcp approval.dbo.테이블명 out c:\perflogs\mytable.txt -S서버IP -U아이디 -P패스워드 -n
   b. 텍스트로 저장하기
     bcp approval.dbo.테이블명 out c:\perflogs\mytable.txt -S서버IP -U아이디 -P패스워드 -c -t$|$ -r$||$

 





 

'MSSQL > 스크립트' 카테고리의 다른 글

MS SQL 작업 스크립트  (0) 2015.12.17
SQL Server 2005 저장 프로시저 디버깅  (0) 2010.10.01

SQL Server 2005를 사용하면서 매우 아쉬웠던 부분중에 하나가 저장 프로시저 디버깅 기능이 빠졌다는 것이다. 2000의 쿼리분석기의 디버깅 사용하기 위한 설정이 어려웠긴 했지만 일단 가능하면 매우 유용하다.

Visual Studio를 깔면 디버깅이 가능하지만 닷넷 개발환경이 아니어서 Visual Studo 라이센스가 없는 현재 내 입장에서는 그림의 떡인 기능이다.

일반적인 IDE와 같은 디버깅 기능을 사용하지는 못하지만 프로필러(SQL Server Profiler)를 이용해 디버깅에 도움을 얻을 수있다.


EventClass 에서 빨간색 Exception 이 되는부분이 실제 에러가 나는 부분이며 그 바로 앞줄이 문제의 원인 부분이다.

1. 프로필러 실행하여 다음 이벤트와 열을 선택한다.
이벤트

   
 Errors and Warnings Attention
ErrorLog 

EventLog

Exception

Exchange Spill Event

Execution Warnings

Hash Warning

Missing Column Statistics

Missing Join Predicate

Sort Warnings

User Error Message
Stored Procedure RPC Output Parameter

RPC:Completed

RPC:Starting

SP:CacheHit

SP:Completed

SP:Recompile

SP:Starting

SP:StmtCompleted

SP:StmtStarting

 

 EventClass
 TextData
 HostName
 DatabaseName
 ObjectName
 LoginName
 CPU
 Reads
 Writes
 Duration
 Rowcount
 LineNumber
 SPID
 StartTime
 EndTime
 ApplicationName
 EventSequence
 RequestID
 TransactionID
 XactSequence

당연 이렇게 다 일일이 선택하기 어려우기에 파일 첨부합니다

다운 받아서 프로필러 템플릿에 추가하면 된다.

프로필러 실행 / 파일 / 템플릿 / 템플릿 가져오기




자 이제 프로시저의 어느 부분에서 에러가 발생하는지 시작해 보도록 하자

1. 프로필러 실행 / 파일 / 새 추적
  템플릿 사용 에 꼭 SP_DEBUG 선택


2. 이벤트 선택 탭 / 열 필터
  ObjectName에 디버깅할 sp이름을 적어주자
  DatabaseName에 DB명을 적어주면 좀더 수월


3. 프로필러 실행을 하고 실제 프로시저가 작동되는지 테스트
 

  DELETE TB_TEST_PARENT 구문을 실행하다가 제약조건 때문에 실패 한것을 알수 있다
  실제 디버깅에 비해서는 매우 미약하지만 기존의 어떤 힌트도 얻지 못한것에 비하면 많은
  도움이 될것으로 생각된다

'MSSQL > 스크립트' 카테고리의 다른 글

MS SQL 작업 스크립트  (0) 2015.12.17
bcp 사용방법  (0) 2010.12.03

+ Recent posts