반응형
반응형
CREATE PROC blackbox
AS
DECLARE @TraceID INT

EXEC sp_trace_create @TraceID OUTPUT, 8
EXEC sp_trace_setstatus @TraceID, 1
RETURN
GO
EXEC sp_procoption blackbox, 'startup', 'on'
GO




--=========================================================================

blackbox는 SQL 서버에 보내진 마지막 5MB 분량의 T-SQL 문장을 가진 특별한 추적 파일로

추적 정보를 \Data 디렉터리의 blackbox.trc 파일에 추가하도록 추적을 정의합니다.

추적이 시작되면 파일 크기가 5MB에 도달할 때까지 추적 정보가 blackbox.trc 파일에 기록됩

니다. 그런 다음 추적은 다른 추적 파일인 blackbox_1.trc를 만들고 추적 정보를 새 파일에 기록

합니다. blackbox_1.trc의 크기가 5MB가 되면 추적이 blackbox.trc로 전환됩니다. 따라서 항상

최고 5MB의 추적 정보를 사용할 수 있습니다.


SQL 서버가 명확하지 않은 이유로 갑자기 죽을경우 blackbox 추적을 통해 문제해결의 실마리

를 찾을 수 있을것입니다.

 

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[trace_blackbox]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[trace_blackbox]
GO

CREATE PROCEDURE trace_blackbox (
 @on int = 2 
)
AS
Begin
 DECLARE @traceid int
 DECLARE @blackboxstatus int
 DECLARE @dir nvarchar(80)

 SET @traceid = 0
 SET @blackboxstatus = 0
 SET NOCOUNT ON


 SELECT @traceid = traceid FROM :: fn_trace_getinfo(0) 
 WHERE property = 1 and value = 8


 -- 추적을 중지하고 추적파일을 삭제
 IF @on = 0 and @traceid > 0 BEGIN
  SELECT @blackboxstatus = cast(value as int) FROM :: fn_trace_getinfo(0) 
  WHERE traceid = @traceid and property = 5
     
  --stop blackbox trace
  IF @blackboxstatus > 0 
   exec sp_trace_setstatus @traceid,0 
     
  --delete blackbox trace definition 
  exec sp_trace_setstatus @traceid,2 
   END

 -- 추적을 시작
 IF @on = 1
  BEGIN
   --create blackbox trace
   IF @traceid < 1 exec sp_trace_create @traceid OUTPUT, 8
   
   --start blackbox trace
   exec sp_trace_setstatus @traceid,1 
  END

 -- 추적 메시지 표시
 SET @traceid = 0
 SET @blackboxstatus = 0

 SELECT @traceid = traceid FROM :: fn_trace_getinfo(0) 
 WHERE property = 1 and value = 8

 SELECT @blackboxstatus = cast(value as int) FROM :: fn_trace_getinfo(0) 
 WHERE traceid = @traceid and property = 5

 --추적이 실행중이면
 IF @traceid > 0 and @blackboxstatus > 0
  BEGIN
   --추적파일이 저장되는 경로와 파일이름을 찾아온다.
   SELECT @dir = cast(value as nvarchar(80))+'.trc' FROM :: fn_trace_getinfo(0) 
   WHERE traceid = @traceid and property = 2
      
   SELECT 'The blackbox trace is running and the trace file is in the following directory.' MESSAGE
      
   SELECT @dir FileName
  END
 ELSE 
  SELECT 'The blackbox trace is not running.' MESSAGE

 SET NOCOUNT OFF

End

 

/*
To start the blackbox trace, type the following command in a SQL Server Query Analyzer window: 
trace_blackbox 1
    
To check the status of the blackbox trace, issue the following command: 
trace_blackbox
    
To stop the blackbox trace, issue the following command: 
trace_blackbox 0
*/


반응형

'연구개발 > DBA' 카테고리의 다른 글

연습문제  (0) 2012.01.16
테이블의 행 구조  (0) 2012.01.16
테이블 변수 vs 임시 테이블  (0) 2012.01.09
Admin::Started with SQL Server (서비스시작) 추적플래그 trace  (0) 2012.01.08
MSSQL CHECKPOINT  (0) 2012.01.08
반응형
테이블 변수에는 고유(unique) 인덱스와 유사한 역할을 하는 PRIMARY KEY 제약 조건과 UNIQUE 제약 조건을 지정하는 것 외에,
명시적으로 인덱스를 생성할 수 없다.
고유하지 않은 인덱스는 생성할 수 없다. 고유하지 안은 칼럼에 인덱스를 생성해야 한다면 다른 칼럼을 추가하여 고유성을 보장하게 한 다음,
복합 칼럼에 PRIMARY KEY 제약 조건이나 UNIQUE 제약 조건을 생성해야 한다.

테이블 변수는 생성할 때 선언된 테이블의 스키마 정의를 변경할 수 없다. 결국 DECLARE 명령에 모든 스키마 정의를 포함시켜야 한다.
이러한 제한사항으로 인해 재컴파일의 가능성이 그만큼 감소하는 것이다.
스키마가 변경되면 재컴파일의 원인이 된다는 것을 유념해야 한다.

SQL Server 2000에서는 테이블 변수에 SELECT INTO 구문과 INSERT EXEC 구문을 사용할 수 없었다. 하지만, SQL Server 2005에서는 INSERT EXEC 구문을 사용할 수 있도록 개선되었다.

테이블 변수 이름으로 칼럼 이름을 식별할 수 없다. 이로 인해 ,테이블 변수의 칼럼을 상관 서브쿼리에서 참조하는 경우, 칼럼 이름이 모호해질 수 있다는 문제점이 있다.

테이블 변수를 변경하는 쿼리에서는 병렬 쿼리 실행 계획을 사용할 수 없다.


테이블 변수는 문장 단위 롤백 기능을 지원하기 위해서 트랜잭션 영역이 문장 수준으로만 제한된다.

일반적으로 SQL 서버 2000에서 테이블 변수를 사용하는 경우와 임시 테이블을 사용하는 경우에 성능상의 차이가 있습니까?

 

테이블 변수를 사용하는 방법과 임시 테이블을 사용하는 방법 간에는 큰 성능상의 차이가 있다. 대부분의 경우에 임시 테이블이 테이블 변수보다 속도가 빠르다. 필자는 다음에 소개하는 팁을 필자가 활동하고 있는 사설 SQL 서버 뉴스그룹으로부터 얻었고, 마이크로소프트로부터 독자 여러분에게 공개해도 된다는 허락을 받았다. 쿼리를 테이블 변수를 사용하여 작성한 경우에는 SMP(동기 다중 프로세서) 환경하에서도 병렬처리 쿼리 계획을 생성하지 않게 되지만, 실제로 동일한 역할을 하는 쿼리를 로컬 또는 전역 임시 테이블을 사용하여 작성하게 되면 병렬처리 쿼리 계획을 생성하기 때문에 성능상의 차이가 발생하게 된다.

SQL 서버 개발팀의 고위 관계자는 테이블 변수를 사용하게 되면 내부적인 메타 데이터를 사용하기 때문에, 테이블 변수를 사용하게 되면 SQL 서버 엔진 내에서 병렬처리 쿼리 계획을 생성하지 못한다는 정보를 제공해 주었다. 또한 SQL 서버는 임시 테이블을 포함하고 있는 쿼리에 대한 통계값은 지속적으로 관리하게 되지만, 테이블 변수를 포함하고 있는 쿼리에 대한 통계값은 유지하지 않는다. 통계값이 없기 때문에 SQL 서버는 테이블 변수를 포함하고 있는 쿼리에 대해서 잘못된 쿼리 처리계획을 생성할 수도 있다. 또한 SQL 서버 개발팀에서는 SQL 서버의 테이블 변수는 가능하다면 소규모의 쿼리나 데이터 집합을 위한 용도로 사용하고, 대용량 데이터 집합을 처리하기 위해서는 임시 테이블을 사용하는 것이 바람직하다고 권고한다.

테이블 변수에 대한 이러한 권고는 지금까지 마이크로소프트 측에서 테이블 변수는 메모리 내에서 생성되기 때문에 좀 더 빠른 성능을 제공한다는 주장과 일부 상충하는 면이 있다. 하지만 실제로 테이블 변수의 경우도 임시 테이블과 거의 유사한 디스크 I/O를 발생시킨다.

실제로 테이블 변수를 사용할 것인지 임시 테이블을 사용할 것인지를 결정하려고 할 때는 실제 환경에서 두 가지 경우를 모두 구현한 다음 서로 비교해 보고 선택하는 것이 바람직하다. 필자의 경우에는 대부분 결과집합이 커질수록 임시 테이블을 사용하는 것이 더 빠른 성능을 제공한다는 점에 대해서는 약간의 의문을 가지고 있다. 테이블 변수에 대한 좀 더 자세한 정보는 마이크로소프트 기사 ”정보:FAQ-SQL 2000 테이블 변수”(http://support.microsoft.com/default.aspx?scid=kb;en-us;305977)를 참조한다.

 

 

클러스터된 인덱스를 다시 만들 떄 CREATE INDEX 구문에 DROP EXISTING 절 사용

 

넌클러스터(nonclustered) 인덱스의 내부 구조는 해당 테이블에 클러스터된 인덱스가 존재하는지 여부에 따라 결정된다. 클러스터 인덱스가 있는 테이블을 클러스터된 테이블이라고 하고, 클러스터된 인덱스가 없는 테이블을 힙(heap) 테이블이라고 한다. 힙 테이블에 만들어진 넌클러스터 인덱스의 경우에는 SQL 서버가 넌클러스터 인덱스의 리프 레벨에서 데이터 페이지를 찾기 위해서 행ID(RID)를 사용하게 된다. ID를 인덱스내부에 포함하게 되면 데이터가 변경되었을 때 넌클러스터 인덱스를 유지관리하는 데에 연관된 오버헤드를 최소한으로 줄여줄 수 있기 때문에 성능향상에 도움이 된다(넌클러스터 인덱스에 대한 좀 더 자세한 정보는 Kalen Delaney 2001 9월호 “튜닝할 시점” 기사와 2001 10월호의 “커버된 인덱스” 기사를 참조한다).

하지만 클러스터된 인덱스가 존재하는 테이블의 넌클러스터 인덱스의 경우에는 데이터 페이지를 찾기 위한 행식별자로 행ID가 아닌 클러스터된 인덱스에 포함된 키를 사용하기 때문에, 만약 넌클러스터 인덱스가 존재하고 있는 테이블의 클러스터된 인덱스를 삭제하게 되면, SQL 서버는 각 레코드의 위치를 지정하는 지시자의 역할을 기존 클러스터된 인덱스의 키에서 다시 행ID를 사용할 수 있도록 변경시켜 주기 위해, 해당 테이블에 존재하는 모든 넌클러스터 인덱스를 삭제하고 다시 생성하게 된다. 반대로 이미 넌클러스터 인덱스가 존재하고 있는 테이블에 클러스터된 인덱스를 추가하는 경우에도 기존의 넌클러스터 인덱스의 내부구조에서 사용하고 있던 행ID 대신 클러스터된 인덱스의 키를 포함할 수 있도록 반드시 한 번은 넌클러스터 인덱스를 삭제하고 다시 생성하는 작업을 수행하게 된다. 넌클러스터 인덱스를 삭제하고 다시 생성하는 작업은 대상 테이블이 매우 대용량인 경우에는 상당히 많은 시간과 디스크 I/O, CPU 시간을 사용하게 된다.

클러스터된 인덱스를 변경할 때 CREATE INDEX 구문에 DROP_EXISTIING 절을 함께 사용하게 되면 좀 더 빠르게 작업할 수 있다. DROP_EXISTING 절은 SQL 서버가 클러스터된 인덱스를 삭제하고 다시 만들 때 기존에 존재하고 있던 넌클러스터 인덱스에 포함되어 있는 클러스터된 인덱스의 키 부분을 삭제하지 않고 새로 만들어진 클러스터된 인덱스의 키로 변경시키도록 하는 역할을 한다. (DBCC DBREINDEX 명령을 사용하게 되면 기존에 존재하는 클러스터된 인덱스를 다시 만드는 작업을 할 때 SQL 서버가 넌클러스터 인덱스를 새로 생성하는 작업을 수행하지 않도록 해 준다. 하지만 DBCC DBREINDEX 명령은 기존 인덱스에 포함되어 있는 컬럼 간의 위치를 이동시키기 위해서는 사용할 수 없다). 결국 DROP_EXISTING 절을 사용하게 되면 넌클러스터 인덱스를 삭제하고 다시 만드는 전체 과정에 소요되는 시간 및 자원을 절감할 수 있게 되는 것이다. 추가적으로, 기존에 존재하는 클러스터된 인덱스의 키를 변경하지 않고 UNIQUE 옵션만을 추가한 경우에는 SQL 서버가 기존에 존재하고 있는 넌클러스터 인덱스를 다시 만드는 작업을 하지 않기 때문에, 클러스터된 인덱스에 UNIQUE 옵션만 추가했다고 해서 확실한 성능의 개선이 되는 것은 아니다. DROP_EXISTING 절은 클러스터된 인덱스와 넌클러스터 인덱스가 공존하는 테이블의 클러스터된 인덱스를 수정하는 작업을 수행할 때 시간 및 자원을 효과적으로 절감해 주는 유용한 기능으로 사용할 수 있다.

반응형

'연구개발 > DBA' 카테고리의 다른 글

테이블의 행 구조  (0) 2012.01.16
trace blackbox  (0) 2012.01.15
Admin::Started with SQL Server (서비스시작) 추적플래그 trace  (0) 2012.01.08
MSSQL CHECKPOINT  (0) 2012.01.08
DMV를 활용한 병목 점검 예제  (0) 2012.01.04
반응형

SQL Server  수동 시작

  •   SQL Server 구성 관리자 :: 로컬 SQL Server 또는 SQL Server 에이전트 서비스의 인스턴스를 시작, 일시 중지, 재개 및 중지합니다.
  •  명령 프롬프트 : net start , sqlservr.exe 실행하여 SQL Server or SQL Server Agent 인스턴스 시작합니다.

    • 직접 입력한 모든 명령 프롬프트 옵션은 SQL Server 설치 동안 Windows 레지스트리에 기록된 기본 명령 프롬프트 옵션보다 우선합니다.
    • 문제 해결을 목적으로 SQL Server 를 시작하려는 경우에만 명령 프롬프트에서 sqlservr.exe를 실행하십시오.
    • Windows를 로그오프하기 전에 SQL Server 인스턴스를 종료해야 합니다.

 net 명령

  1. --  sql server 시작
  2. net start "SQL Server(MSSQLSERVER)" or net start MSSQLSERVER
  3. net start "SQL Server(instancename)" or net start MSSQL$instancename
  4.  

     

  5. -- 시작옵션
  6. net start MSSQLSERVER /f /m /T trace_flag
  7. -- 일시 중지 / 재개
  8. net pause MSSQLSQLSERVER   / net continue MSSQLSERVER
  9.  
  10. -- 서비스 중지
  11. net stop MSSQLSERVER

 

sqlserver.exe

  • SQL Server를 시작할 수 있는지 테스트하는 목적 이외에는 명령줄에서 SQL Server를 실행하지 마십시오. 명령줄에서 SQL Server를 시작한 후 유지 관리 작업을 수행하면 나중에 오류가 발생할 수 있습니다. 예를 들어 관리자로 로그인하여 새 데이터베이스를 만들거나 데이터 파일의 위치를 변경하면 나중에 SQL Server 서비스의 일반 계정에서 SQL Server를 실행한 경우 해당 데이터베이스나 데이터 파일에 액세스할 수 없습니다.
  • cd \Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn 에 위치

     

  1. -- sql server  시작
  2. sqlservr.exe
  3. sqlservr.exe -s <instancename>
  4. -- 단일 사용자 모드로 실행
  5. sqlservr.exe -m
  6. sqlserver.exe -m -s <instancename>
  7. -- 인스턴스를 최소 구성으로 시작하려면
  8. sqlserver.exe -f
  9. -- 추적 플래그
  10. sqlserver.exe -Ttrace_flag
  11.  
  12. -- sql server 중지
  13.  Ctrl +Break를 누르거나 명령창을 닫습니다.

 

서비스 시작옵션 (Using the SQL Server Service Startup Options)

  • 서비스 시작되면서 필요한 추척 플래그 옵션 참고 하십시오.

    기본시작옵션 설명
     -d master_file_path

     master 데이터베이스 파일의 정규화된 경로

    C:\Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\Data\master.mdf

    제공되지 않으면 기존의 레지스트리 매개 변수 사용

     -e error_log_path

     오류 로그 파일의 정규화된 경로입니다.

     C:\Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\LOG\ERRORLOG

     -I master_log_path

    master 데이터베이스 로그 파일의 정규화된 경로입니다. 일반적으로

    C:\Program Files\Microsoft SQL Server\MSSQL.n\MSSQL\Data\mastlog.ldf입니다.

     -c  

     명령 프롬프트에서 SQL 을 시작할때 시간을 단축 시킵니다.

     -f   SQL Server 인스턴스를 최소 구성으로 시작합니다.  예를 들어 오버커밋 메모리 같은 구성 값의 설정 대문에 서버를 시작할 경우에 유용
     -g memory_to_reserve

     SQL Server에서 SQL Server 프로세스 내(단, SQL Server 메모리 풀 외부)의 메모리 할당에 대해 사용 가능하도록 둘 메모리를 MB 단위의 정수로 지정합니다.

    SQL Server 오류 로그에서 다음 경고가 표시되지 않으면 -g 매개 변수의 기본값을 사용해야 합니다.

    "Failed Virtual Allocate Bytes: FAIL_VIRTUAL_RESERVE <size>"
     "Failed Virtual Allocate Bytes: FAIL_VIRTUAL_COMMIT <size>"

     -h 32비트 SQL Server 2005에서 AWE가 사용된 경우 Hot Add 메모리 메타데이터에 대해 가상 주소 공간을 예약합니다. 32비트 AWE가 사용된 Hot Add 메모리에 필요하지만 가상 주소 공간에서 약 500MB를 사용하고 메모리 튜닝도 더 어렵게 만듭니다. 64비트 SQL Server에는 필요하지는 않습니다. Hot Add 메모리는 Enterprise Edition 및 Datacenter Edition에서만 사용할 수 있습니다. 또한 하드웨어 공급업체의 특수한 하드웨어 지원이 필요합니다.
     -n

     SQL Server 이벤트를 기록하는 데 Windows 응용 프로그램 로그를 사용하지 않습니다.

    -n으로 SQL Server 인스턴스를 시작하는 경우 -e 시작 옵션을 함께 사용하는 것이 좋습니다.

     -s  s 매개 변수를 설정하지 않으면 기본 인스턴스가 시작을 시도합니다.
     -T trace#  지정된 추적 플래그(trace#) 적용 시 SQL Server 인스턴스를 시작해야 함을 나타냅니다. 추적 플래그는 비표준 동작으로 서버를 시작하는 데 사용합니다.
     -x CPU 시간과 캐시 적중률 통계를 유지할 수 없도록 합니다. 최고의 성능을 허용합니다.

 

  1.  

    Sqlservr.exe c –mT3609T4022

  2.  

    3609 : SQL시작시 tempdb 생성 skip

    4022 : SQL시작시 실행되는 sp무시

반응형
반응형
- Check Point ,발생 시 데이터의 변경된 부분 (Dirty Page)이 실제 Disk에 반영된다.

--(테스트 환경 및 이상 현상시) 체크 포인트 발생시 로그를 디스크에 기록하지 않고 버리라고 하는 옵션
sp_dboption 'alice_game','trunc. log on chkpt.','true';


--상세한 SQL 옵션이 보이지 않을 경우
sp_configure 'show advanced options',1
RECONFIGURE WITH OVERRIDE

sp_configure
--recovery interval (min)
/*
* 검사점 발생 상황
- 명시적인 Checkpoint 명령어 실행
- 로그 용량이 70%이상 찼고 데이터베이스가 SIMPLE 모드 일 경우
- 긴 복구 시간이 예상될 경우 (SQL 기본값은 1분)
•검사점은 sp_configure 의 복구 간격 옵션을 사용하여 조정이 가능하다.
물론 시작시 -T3502 플래그를 설정하여 검사점 실행시 이벤트 로그에 로그를 남길 수 도 있다.

•검사점 레코드는 트랜잭션 로그에 기록된다.


*/
반응형
반응형

DMV를 활용한 병목 점검 예제


카탈로그 뷰

디스크에 관리되는 메타 데이터이다.
DDL 문으로 생성된 오브젝트들이 반영된 뷰이다.
DBA가 사용자 생성 오브젝트들의 이름과 구조를 확인하는데 사용한다.


DMV

변화하는 서버의 상태 정보를 제공한다. (다중의 세션들, 다중의 트랜잭션, 다중의 요청과 관련)
서버 프로세스 자체 내부 또는 서버의 모든 세션들에 대하여 진행 중인 일들이 반영된다.
진단, 메모리 튜닝, 프로세스 튜닝, 서버 내의 모든 세션들을 모니터링하는데 사용된다


카탈로그 뷰

SQL Server 2005 데이터베이스 엔진이 사용하는 정보를 반환하는 뷰
카탈로그 메타 데이터에 대한 일반적인 인터페이스를 제공하면서, 메타 데이터를 사용자가 보기 편한 형태로 변환하여 보여 주는 가장 효율적인 방법 ? 시스템 테이블을 직접 쿼리하지 말고, 카탈로그 뷰를 사용하는 것을 권고함
사용자가 사용 가능한 카탈로그 메타 데이터는 모두 카탈로그 뷰로 제공됨
예;
sys.tables
sys.procedures
sys.indexes
개별 카탈로그 뷰에 대한 정보는 SQL Server Books Online 참조 요망

 

카탈로그 뷰 종류
--------------------------------------------------

CLR Assembly Catalog Views
Databases and Files Catalog Views
Database Mirroring Catalog Views
Data Spaces and Fulltext Catalog Views
Endpoints Catalog Views
Extended Properties Catalog Views
Linked Servers Catalog Views
Messages (For Errors) Catalog Views
Objects Catalog Views
Partition Function Catalog Views
Scalar Types Catalog Views
Schemas Catalog Views
Security Catalog Views
Service Broker Catalog Views
Server-wide Configuration Catalog Views
XML Schemas (XML Type System) Catalog Views


일반적인 서버 DMV와 DMF
-----------------------------------------------------

<<서버 레벨>>
- dm_exec_* : 사용자 코드와 관련 커넥션들의 실행

- dm_os_*: 메모리, 잠금, 스케줄링과 같은 low level system (server-wide) 정보
- dm_tran_*: 트랜잭션과 격리 (isolation)
- dm_io_*: 네트워크와 디스크 상에서의 Input/Output
- dm_db_*: 데이터베이스와 데이터베이스 오브젝트


<<컴포넌트 레벨>>


- dm_repl_*: 복제 (Replication)
- dm_broker_*: SQL 서비스 브로커
- dm_fts_*: 전체 텍스트 검색 (Full Text Search)
- dm_qn_*: Query Notifications
- dm_clr_*: Managed code의 CLR 실행

전형적인 리소스 이슈

CPU
Memory
IO
인덱스
잠금 (Locking)
네트워크

 

DMV를 활용한 모니터링

현재 실행 중인 SQL 문 확인
리소스를 많이 사용하는 상위 저장 프로시저 및 일괄 처리(Batch)
Parallelism
대기
블로킹 및 교착 상태
쿼리 실행 계획
컴파일과 재컴파일
인덱스 활용
Tempdb 사용
커서 사용

 

리소스 병목 찾기CPU: 현재 실행 중인 SQL 문

=================================================================

select r.session_id
  ,status
  ,substring(qt.text,r.statement_start_offset/2,
   (case when r.statement_end_offset = -1
   then len(convert(nvarchar(max), qt.text)) * 2
   else r.statement_end_offset end -    r.statement_start_offset)/2)
  as query_text   -- 이쿼리를실행하는시점에실행되는SQL문
  ,qt.dbid
  ,qt.objectid
  ,r.cpu_time
  ,r.total_elapsed_time
  ,r.reads
  ,r.writes
  ,r.logical_reads
  ,r.scheduler_id
from sys.dm_exec_requests r
cross apply sys.dm_exec_sql_text(sql_handle) as qt
where r.session_id > 50
      and r.session_id <> (select  @@SPID)  -- 자기 자신 쿼리는 제외
order by r.scheduler_id, r.status, r.session_id

 

=================================================================

리소스 병목 찾기
CPU를 많이 사용하는 상위 프로시저 및 일괄처리(Batch)

 

select top 50
sum(qs.total_worker_time) as total_cpu_time,
sum(qs.execution_count) as total_execution_count,
count(*) as  '#_statements',
qt.dbid, qt.objectid, qs.sql_handle,
qt.[text]
from sys.dm_exec_query_stats as qs
cross apply sys.dm_exec_sql_text (qs.sql_handle) as qt
group by qt.dbid,qt.objectid, qs.sql_handle,qt.[text]
order by sum(qs.total_worker_time) desc,qs.sql_handle

select top 50
sum(qs.total_worker_time) as total_cpu_time,
sum(qs.execution_count) as total_execution_count,
count(*) as  '#_statements',
qt.dbid, qt.objectid, qs.sql_handle,
qt.[text]
from sys.dm_exec_query_stats as qs
cross apply sys.dm_exec_sql_text (qs.sql_handle) as qt
group by qt.dbid,qt.objectid, qs.sql_handle,qt.[text]
order by sum(qs.total_worker_time) desc,qs.sql_handle


====>

 total_cpu_time     total_execution_count     #_statements     dbid     objectid     sql_handle   text
 
 
 Statement별 Top CPU 사용
                                     
SQL2005
-- Avg CPU Time 기준 상위 50개 SQL 문
SELECT TOP 50
        qs.total_worker_time/qs.execution_count as [Avg CPU Time],
        SUBSTRING(qt.text,qs.statement_start_offset/2,
   (case when qs.statement_end_offset = -1
   then len(convert(nvarchar(max), qt.text)) * 2
   else qs.statement_end_offset end -qs.statement_start_offset)/2)
  as query_text,
  qt.dbid,
  qt.objectid
FROM sys.dm_exec_query_stats qs
cross apply sys.dm_exec_sql_text(qs.sql_handle) as qt
ORDER BY
        [Avg CPU Time] DESC

 


-------------------->

 

 Avg CPU Time     query_text 

CPU ? 병렬로 실행중인 프로세스 확인       


DW의 경우에는 병렬처리(Parallelism)가 좋지만, OLTP의 경우에는 병렬처리가 반드시 좋은 것만은 아님
SQL 2000 ? 지원하지 않음

SQL 2005
select r.session_id,
 r.request_id,
 max(isnull(exec_context_id, 0)) as number_of_workers,
 r.sql_handle,
 r.statement_start_offset,
 r.statement_end_offset,
 r.plan_handle
from sys.dm_exec_requests r
 join sys.dm_os_tasks t on r.session_id = t.session_id
 join sys.dm_exec_sessions s on r.session_id = s.session_id
where s.is_user_process = 0x1
group by r.session_id, r.request_id, r.sql_handle, r.plan_handle,
r.statement_start_offset, r.statement_end_offset
having max(isnull(exec_context_id, 0)) > 0

                    
                    
                    
CPU: Parallelism과 CPU 사용        

select
qs.sql_handle,
qs.statement_start_offset,
qs.statement_end_offset,
q.dbid,
q.objectid,
q.number,
q.encrypted,
q.text
from sys.dm_exec_query_stats qs
 cross apply sys.dm_exec_sql_text(qs.plan_handle) as q
where qs.total_worker_time > qs.total_elapsed_time

CPU: 컴파일 시간

SQL 2005 ? before / after 스냅샷을 관리함
최적화 과정에 소요된 시간은 일반적으로 최적화를 위하여 사용된 CPU 시간과 유사함

Select * from sys.dm_exec_query_optimizer_info

counter                 occurrence           value                                                
---------------       -----------------   ------------------------------------------------
optimizations         81                       1.0
elapsed time          81    .064547820702944486

 

CPU Pressure: 재컴파일

select top 25
 sql_text.text,
 sql_handle,
 plan_generation_num,
 execution_count,
 dbid,
 objectid
from sys.dm_exec_query_stats a
 Cross apply sys.dm_exec_sql_text(sql_handle) as sql_text
where plan_generation_num >1
order by plan_generation_num desc

 

메모리가 어디에 얼마나 할당되어 있는지 점검
내부 서버 컴포넌트들
Sys.dm_os_memory_clerks
Dm_exec_requests
SPs, Sorts
Worker threads
Sys.dm_os_workers
Memory grants pending
Sys.dm_os_wait_stats
SQLServer : Memory Manager ? Memory Grants Pending
 얼마나 많은 사용자 또는 프로세스가 메모리 허가를 기다리고 있는지 확인 가능. 메모리가 부족하면 더 많은 수의 사용자 프로세스들이 메모리를 대기하게 되므로 Memory Grants Pending 값 증가함.


 database_id     object_id     objname                    index_id     buffer_count   
 --------------  ------------  -------------------------  -----------  ---------------
 32767           60            sysobjvalues               1            2705           
 32767           41            syscolpars                 1            334            
 4               60            sysobjvalues               1            87             
 1               60            sysobjvalues               1            80             
 4               41            syscolpars                 1            63             
 32767           34            sysschobjs                 1            56             
 4               94            sysobjkeycrypts            1            32             
 32767           94            sysobjkeycrypts            1            28             
 32767           34            sysschobjs                 3            27             
 1               41            syscolpars                 1            23             
 
 
 
 
 리소스 병목 찾기메모리: 오브젝트 및 인덱스를 기준으로 한 상위 메모리 사용
 
 
 
 메모리 버퍼를 오브젝트 별로 분류 (테이블,인덱스)

select b.database_id
  ,p.object_id
  ,object_name(p.object_id) as objname
  ,p.index_id
  ,buffer_count=count(*)
from sys.allocation_units a,
  sys.dm_os_buffer_descriptors b,
  sys.partitions p
where a.allocation_unit_id = b.allocation_unit_id
and a.container_id = p.hobt_id
group by b.database_id,p.object_id, p.index_id
order by buffer_count desc


리소스 병목 찾기
IO를 많이 발생시키는 상위 SQL 문


SELECT TOP 50
        (qs.total_logical_reads + qs.total_logical_writes) /qs.execution_count as [Avg IO],
      SUBSTRING(qt.text,qs.statement_start_offset/2,    (case when qs.statement_end_offset = -1
   then len(convert(nvarchar(max), qt.text)) * 2
   else qs.statement_end_offset end -qs.statement_start_offset)/2)
  as query_text,
  qt.dbid,
  qt.objectid
FROM sys.dm_exec_query_stats qs
cross apply sys.dm_exec_sql_text(qs.sql_handle) as qt
ORDER BY [Avg IO] DESC


-->
 Avg IO     query_text
 
 
 
 리소스 병목 찾기
 파일 별 IO 대기
 
 
 
------------------->

select database_id
  , file_id
  , io_stall,io_pending_ms_ticks
  , scheduler_address
from sys.dm_io_virtual_file_stats (NULL, NULL) as t1,
     sys.dm_io_pending_io_requests as t2
where t1.file_handle = t2.io_handle


 database_id     file_id     io_stall     io_pending_ms_ticks     scheduler_address   
 --------------  ----------  -----------  ----------------------  --------------------


 쿼리 실행 계획 확인
 
 
 
 SQL 2005
실행 계획이 캐시에 남아 있는 한 확인 가능함

 select * from sys.dm_exec_query_plan (plan_handle)
실행 계획이 캐시에서 쫓겨 나는 경우에는, 프로필러로 실행 계획과 통계를 수집

 

리소스 병목 찾기
IO 할당 대기

 

Tempdb (DBID=2)
 Select session_id, wait_duration_ms, resource_description
 From sys.dm_os_waiting_tasks
 Where wait_type like 'PAGE%LATCH_%'
 and resource_description like '2:%'
 
사용자 DB (다음에서 dbid 부분을 db_id() 값을 입력하여 실행하면 됨 )
 resource_description like ‘dbid:%’

Page%Latch 대기 확인
 select * from Sys.dm_os_wait_stats
 
 
 리소스 병목 찾기
 - IO Pressure: 사용되지 않는 사용자 인덱스

 

유용하지 않은 사용자 인덱스를 확인할 수 있음
예제

select object_name(i.object_id), i.name
from sys.indexes i, sys.objects o
where  i.index_id NOT IN (select s.index_id
       from sys.dm_db_index_usage_stats s
    where s.object_id=i.object_id and
    i.index_id=s.index_id and
   database_id = <dbid> )  /* dbid : db_id() 또는 dbid값을 입력 */
and o.type = 'U'
and o.object_id = i.object_id
order by object_name(i.object_id) asc

 

리소스 병목 찾기IO Pressure: 누락된 인덱스

옵티마이저가 누락된 인덱스 정보를 알려 줌
xml plan 참조 요망
Select * from sys.dm_exec_query_plan(plan_handle)

DMV가 상세 정보를 제공함
Sys.dm_db_missing_index_group_stats
Sys.dm_db_missing_index_groups
Sys.dm_db_missing_index_details


리소스 병목 찾기Tempdb 사용


Select SUM (user_object_reserved_page_count)*8 as user_objects_kb,
SUM (internal_object_reserved_page_count)*8 as internal_objects_kb,
SUM (version_store_reserved_page_count)*8  as version_store_kb,
SUM (unallocated_extent_page_count)*8 as freespace_kb
From sys.dm_db_file_space_usage
Where database_id = 2


 user_objects_kb     internal_objects_kb     version_store_kb     freespace_kb   
 ------------------  ----------------------  -------------------  ---------------
 192                 128                     0                    6848       
 
 리소스 병목 찾기
 Tempdb 사용: task 단위
 
 SELECT t1.session_id,
(t1.internal_objects_alloc_page_count + task_alloc) as allocated,
(t1.internal_objects_dealloc_page_count + task_dealloc) as
 deallocated
from sys.dm_db_session_space_usage as t1,
(select session_id,
   sum(internal_objects_alloc_page_count)
      as task_alloc,
   sum (internal_objects_dealloc_page_count) as
  task_dealloc
      from sys.dm_db_task_space_usage group by session_id) as t2
where t1.session_id = t2.session_id and t1.session_id >50
order by allocated DESC


 session_id     allocated     deallocated   
 -------------  ------------  --------------
 51             64            56            
 52             0             0      
 
 
 리소스 병목 찾기
 Tempdb 사용: statement 단위
 
 
select t1.session_id, t1.request_id, t1.task_alloc,
  t1.task_dealloc,t2.sql_handle, t2.statement_start_offset,
t2.statement_end_offset, t2.plan_handle
from (Select session_id, request_id,
                sum(internal_objects_alloc_page_count) as task_alloc,
               sum (internal_objects_dealloc_page_count) as task_dealloc
         from sys.dm_db_task_space_usage
        group by session_id, request_id) as t1, sys.dm_exec_requests as t2
where t1.session_id = t2.session_id and (t1.request_id = t2.request_id)
order by t1.task_alloc DESC


 session_id     request_id     task_alloc     task_dealloc     sql_handle                                        statement_start_offset     statement_end_offset     plan_handle                                     
 -------------  -------------  -------------  ---------------  ------------------------------------------------  -------------------------  -----------------------  ------------------------------------------------
 1              0              0              0                (null)                                            (null)
 
 
 
 리소스 병목 찾기 비효율적인 커서 사용
 
 
     Fetch Buffer 크기가 1행인 API 커서를 사용하는 연결 정보 확인
만약 반드시 커서를 사용해야만 하는 경우라면, Fetch Buffer 크기를 1이 아닌 좀 더 큰 값을 사용하는 것이 보다 효율적임 (예를 들어, 100 행)

 

select cur.* from sys.dm_exec_connections concross apply sys.dm_exec_cursors(con.session_id) as cur
where cur.fetch_buffer_size = 1 and
cur.properties LIKE 'API%' -- API 커서

 

리소스 병목 찾기인덱스 사용 상세 정보


Sys.dm_db_index_operational_stats
인덱스 사용에 대한 통계 자료를 이해하기 쉬운 형태로 제공함
제공 정보
액세스 유형 (예를 들어, 범위 쿼리인지, 단일 룩업인지…)
잠금의 갯수 (예를 들어, 행 잠금, 페이지 잠금 등)
블로킹 또는 대기 발생 횟수
블로킹 또는 대기 유지시간
페이지 래치 대기 발생횟수
페이지 래치 대기 유지시간
잎(Leaf) 레벨에서의 Insert, update, delete 횟수
잎(Leaf) 레벨의 상위 레벨에서의 Insert, update, delete 횟수
잎 레벨에서 병합된 페이지 수 (행 삭제로 인하여 할당 취소된 빈 페이지들을 나타냄)


리소스 병목 찾기:
블로킹과 교착상태(Deadlock) 추적

SQL2005
- 추적 (Trace)
Deadlock
TraceLog에 로깅된 그래픽 형태의 교착 상태 정보
블로킹 당한 프로세스 리포트
사용자가 지정 가능
Exec sp_configure ‘blocked process threshold’,200
블로킹 체인을 TraceLog에 기록
조사 작업은 추후 수행 가능

- Dm_os_waiting_tasks (waiting_task_address, spid, blocking_task_address)
Dm_os_tasks (spid, task_address)
Dm_exec_requests (session_id,request_id)
Task들과 관련되는 잠금
min, max, duration, avg 제공

 

blocked process threshold
 초 단위
 블로킹당한 프로세스 리포트에 대한
  임계치 설정
- 0부터 86,400 까지 설정 가능

 

리소스 병목 찾기블로킹: sp_block


create proc dbo.sp_block (@spid bigint=NULL)
as
-- This stored procedure is provided "AS IS" with no warranties, and confers no rights.
-- Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm
-- This proc reports blocks
-- 1. optional parameter @spid
select t1.resource_type
 , 'database'=db_name(resource_database_id)
, 'blk object' =isnull(object_name(t1.resource_associated_entity_id) ,t1.resource_associated_entity_id)
 ,t1.request_mode
 ,t1.request_session_id   -- spid 
 ,t2.blocking_session_id  -- spid 
from sys.dm_tran_locks as t1,
 sys.dm_os_waiting_tasks as t2
where t1.lock_owner_address = t2.resource_address
and t1.request_session_id = isnull(@spid,t1.request_session_id)


리소스 병목 찾기 - 쿼리 성능 튜닝

 

Sys.dm_exec_requests
Sys.dm_exec_query_stats
현재 캐시에 있는 쿼리 실행 계획 당 한 행
Min, max, avg, last
실행 소요 시간, 물리적 읽기, 논리적 읽기, 쓰기 등
누적 실행 횟수
최초 및 최종 실행 시각
Sys.dm_exec_sql_text(sql_handle)
인 메모리 SQL 텍스트
Sys.dm_exec_query_plan(plan_handle)
인 메모리 실행 계획

디폴트 추적(Default Trace)

 

최소의 부하, 소용량 관리 이벤트
DDL, DBCC, sp_configure 등을 추적
sp_configure로 비활성화 가능함 (‘default trace enabled’ 옵션)
오브젝트 생성, 오브젝트 삭제
인덱스 포함
실무 활용 예: IO spike와 인덱스 삭제의 관련성 분석
시도(attempt)와 실제로 성공한 작업이 모두 포함됨
100 MB 순환 구조
최다 5개의 20 MB 크기 파일에 로깅된다
하나의 파일이 가득 차거나 서버가 재시작되면 새로운 파일이 생성된다
스크립트 예:
  select t.StartTime, t.EventClass, e.name,
  t.DatabaseName, t.ObjectName, t.ObjectID, t.IndexID
from fn_trace_gettable ('C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\LOG\log_10.trc',0) t
  join sys.trace_events e
on e.trace_event_id = t.eventclass
Order by t.StartTime

디폴트 추적 이벤트들Select distinct(eventid) from fn_trace_geteventinfo(1)


18  Audit Server Starts And Stops
20  Audit Login Failed
22  ErrorLog
46  Object:Created
47  Object:Deleted
55  Hash Warning
69  Sort Warnings
79  Missing Column Statistics
80  Missing Join Predicate
81  Server Memory Change
92  Data File Auto Grow
93  Log File Auto Grow
94  Data File Auto Shrink
95  Log File Auto Shrink
102 Audit Database Scope GDR Event
103  Audit Schema Object GDR Event
104 Audit Addlogin Event
105 Audit Login GDR Event
106 Audit Login Change  Property Event
108 Audit Add Login to Server  Role Event
109 Audit Add DB User Event
110 Audit Add Member to DB  Role Event
111 Audit Add Role Event
115 Audit Backup/Restore Event
116 Audit DBCC Event
152 Audit Change Database  Owner
153 Audit Schema Object Take  Ownership Event
155 FT:Crawl Started
156 FT:Crawl Stopped
157 FT:Crawl Aborted
164 Object:Altered
167 Database Mirroring State  Change


요약
누가, 무엇을, 언제, 어디서, 왜

 

서버의 성능이 갑자기 저하되거나 SQL 문이 제 시간에 결과를 반환하지 않거나 서버가 갑자기 다운되는 경우에, 도대체 무슨 일이 일어나고 있는 것일까?
고객이 요청하기 전에 사전에 문제를 해결할 수 있는 방법은 없는가 ?


2005
DMV와 DMF 제공
관리자 전용 연결 기능 제공
부하를 최소로 주는 추적 기능 제공
디폴트 추적
성능 정보


SQLDiag가 수집 가능한 정보

프로필러 추적
블로킹 정보
SQL Server 환경 정보
SQL Server error log
성능 로그
이벤트 로그
MSInfo


SQLDiag 구문

SQLdiag
 { [/? 도움말] }
     | { [/I 환경 설정 파일]
       [/O 출력 폴더 경로]
       [/P support 폴더 경로]
       [/N 출력 폴더 관리 옵션]
       [/C 파일 압축 타입]
       [/B [+]시작 시간]
       [/E [+]종료 시간]
       [/A SQLdiag 어플리케이션 이름]
       [/Q Quiet 모드로 실행]
       [/G Generic 모드로 실행]
       [/R 서비스 등록]
       [/U 서비스 삭제]
       [/L 반복 모드로 실행]
       [/X 스냅샷 모드로 실행] }
     |     { [START | STOP | STOP_ABORT] }
     |     { [START | STOP | STOP_ABORT] /A SQLdiag 어플리케이션 이름 }

사용 예
 SQLDiag /B +01:00:00 /E +03:00:00
 SQLDiag /B +01:00:00 /E 08:30:00
 SQLDiag /B 03:00:00 /X /L
 SQLDiag /I SD_Detailed.XML /O SQLDIAG_20051229 /B 12:10:00 /E 12:11:00
 SQLDiag /B +00:01:00 /E +00:02:00 /N 2




실행 응용프로그램 확인

SELECT es.session_id

,es.program_name

,es.login_name

,es.nt_user_name

,es.login_time

,es.host_name

,es.cpu_time

,es.total_scheduled_time

,es.total_elapsed_time

,es.memory_usage

,es.logical_reads

,es.reads

,es.writes

,st.text

FROM sys.dm_exec_sessions es

LEFT OUTER JOIN sys.dm_exec_connections ec

ON es.session_id = ec.session_id

LEFT OUTER JOIN sys.dm_exec_requests er

ON es.session_id = er.session_id

OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) st

WHERE es.session_id > 50

ORDER BY es.cpu_time DESC

 


반응형
반응형
SELECT Co
FROM (
    SELECT '가나상사' AS Co
    UNION ALL
    SELECT '(주) 가나상사'
    UNION ALL
    SELECT '가다상사'
    UNION ALL
    SELECT 'OK유통'
    UNION ALL
    SELECT '역삼유통'
    UNION ALL
    SELECT '123마트'
    ) x
ORDER BY LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(Co,'사단법인',''),'주식회사',''),'(주)','')))

SELECT Co
FROM (
    SELECT '가나상사' AS Co
    UNION ALL
    SELECT '(주) 가나상사'
    UNION ALL
    SELECT '가다상사'
    UNION ALL
    SELECT 'OK유통'
    UNION ALL
    SELECT '역삼유통'
    UNION ALL
    SELECT '123마트'
    ) x
ORDER BY UNICODE(LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(Co,'사단법인',''),'주식회사',''),'(주)',''))))
반응형

'연구개발 > DBA' 카테고리의 다른 글

MSSQL CHECKPOINT  (0) 2012.01.08
DMV를 활용한 병목 점검 예제  (0) 2012.01.04
동적쿼리 값 반환  (0) 2012.01.02
Deadlock 모니터링 하기  (0) 2011.12.06
페이징 쿼리  (0) 2011.11.29
반응형
DECLARE @IntVariable    INT;
DECLARE @SQLString NVARCHAR(500);
DECLARE @ParamDefinition    NVARCHAR(500);
DECLARE @max_title    VARCHAR(30);

SET @IntVariable = 197;
SET @SQLString = N'SELECT @max_titleOUT = max(JobTitle) FROM AdventureWorks.HumanResources.Employee
                            WHERE BusinessEntityID = @level';
SET @ParamDefinition = N'@level tinyint, @max_titleOUT varchar(30) OUTPUT';
EXECUTE sp_executesql @SQLString, @ParamDefinition, @level = @IntVariable, @max_titleOUT = @max_title OUTPUT;
SELECT @max_title;
반응형
반응형

[예제]

간단한 예제로 TEST하겠습니다. Pubs 데이터베이스의 Sales테이블로 2개의 TEST 테이블을 생성합니다.

 1.png

두개의 프로시저를 생성합니다.

USP_Session1 프로시저는 tbl_deadlock1테이블 6380값의 qty update tbl_deadlock2테이블 7067값의 qty update합니다.

2.png

 

USP_Session2 프로시저는 tbl_deadlock2테이블 7067값의 qty update tbl_deadlock1테이블 6380값의 qty update합니다.

3.png

 

프로시저를 각각 다른 세션에서 실행합니다.

4.png

 

[모니터링]

1. 추적플래그 1204

 

5.png

Deadlock 발생 SQL Server 로그를 확인합니다.

spid 52 희생 당한 것을 확인할 있습니다.

어떤 쿼리문에서 Deadlock 발생하였는지는 UPDATE Line 보고 찾아보아야 합니다.

 

6.png

 
2. 추적플래그 1222
 
 7-1.png
1222 좀더 상세한 정보를 제공합니다. 어떤 구문에서 Deadlock 발생했는지도 보여줍니다.
 
7.png
 
3. Profiler
아래 그림과 같이 Deadlock 이벤트를 추가합니다.
8.png
 

Deadlock graph :  교착 상태의 XML에 대해 설명합니다. 이 클래스는 Lock:Deadlock 이벤트 클래스와 동시에 발생합니다

Lock:Deadlock : 잠금을 얻으려고 시도하는 동안 교착 상태가 발생하여 이 시도가 취소될 때 생성됩니다

Lock:Deadlock Chain : 교착 상태의 각 참가자에 대해 생성됩니다

(설명은 도움말을 참고하였습니다.)

 

9.png  

처음 [Lock:Deadlock Chain] 발생하여 Deadlock 발생된 세션정보를 보여줍니다. 다음 많이 보시던 [Deadlock graph] 나타납니다.

52 세션이 희생당한 것을 있습니다. 다음으로 [Lock:Deadlock] 발생되고 52 세션이 희생당한 것을 다시 확인 있습니다.

[Deadlock graph] 마우스를 올려놓으면 실행된 구문을 확인 있습니다.

spid52 RID: 2:1:121:0에 X잠금을 spid53 RID: 2:1:148:4 X잠금을 획득했습니다.

그리고 spid52 RID: 2:1:148:4에 U잠금을 획득하려고 하지만 이미 spid53 잠금을 획득한 상태이고,

spid53 RID: 2:1:121:0에 U잠금을 획득하려고 하지만 spid52 이미 잠금을 획득하여 Deadlock 빠집니다.

4. 성능 모니터
성능 모니터에 SQLServer:Locks Number of Deadlocks/sec 카운터를 추가합니다. (window7 입니다.)
10.png
 
11.png
 
 
5. 시스템테이블, 시스템저장프로시저, DMV
 
12.png
spid53 52 차단하고 있고 spid52 53 차단하고 있는것을 있습니다.
13.png
 
14.png
15.png
 
 
16-1.png
어떤 spid에서 차단당한 것인지는 머릿속으로 계산이 필요하겠지요.;;
16.png
 
 

[정리]

평상시에는 성능모니터의 Number of Deadlocks을 수집하여 Deadlock 발생하는지 확인을 합니다.

Deadlock 발생된다면 추적플래그, DMV, profiler 등을 확인하는 것이 어떨까 합니다.

 

또한 테이블에는 인덱스가 반드시 있어야 합니다.

Deadlock 아니더라도 인덱스가 없다면 테이블락이 자주 발생 있고 차단이 많이 발생하게 됩니다. 

 

근데.. Deadlock은 찾았는데……... 어떻게 해결해야 할까요????

Deadlock 예제처럼 단순한 경우에만 발생하는 것이 아니다보니.. 부분은 기회가 되면 다음에 다뤄보겠습니다.

부족한  읽어주셔서 감사합니다.^^

 

ps. 외에 모니터링 할 있는 다른 방법을 알고 계시면 공유해주세요. ^^

반응형
반응형
ALTER PROC [dbo].[prGetNoticeList]
    @TypeID                smallint,
    @PageNo                int,
    @PageSize            tinyint,
    @IsShow                char(1)=null,
    @SearchKey            nvarchar(10) = null,
    @SearchString        nvarchar(10) = null
AS       


SET NOCOUNT ON
    DECLARE @StrSQL nvarchar(1000), @Param nvarchar(200), @SearchPart nvarchar(120), @TotalRow int
    DECLARE @LastPage int, @LastPageRow int

    SET @SearchPart = N''

    IF @IsShow IS NOT NULL
        SET @SearchPart = @SearchPart +  N' AND IsShow = @IsShow '

    IF  @SearchKey IN ('Title','Contents') AND @SearchString <> ''       
        SET @SearchPart = @SearchPart + N' AND Contains(' + @SearchKey + N' , @SearchString)'
   
    --------------------------------------------------------------------------------------------
    -- 총 레코드수 구하기
    --------------------------------------------------------------------------------------------
    SET @Param =  N'@TypeID smallint, @IsShow char(1), @SearchKey varchar(10), @SearchString varchar(10), @TotalRow int output'

    SET @StrSQL = 'SELECT @TotalRow=Count(NoticeNo) FROM dbo.Notice WHERE TypeID=@TypeID ' + @SearchPart
    EXEC sp_executesql @StrSQL, @Param, @TypeID, @IsShow, @SearchKey, @SearchString, @TotalRow output

    --------------------------------------------------------------------------------------------
    -- 마지막페이지수, 레코드수
    --------------------------------------------------------------------------------------------
    SET @LastPageRow = @TotalRow - (@TotalRow/@PageSize) * @PageSize

    IF @LastPageRow = 0        SET @LastPage = (@TotalRow/@PageSize)   
    ELSE                    SET @LastPage = (@TotalRow/@PageSize) +1


    IF @PageNo = 1                            -- 첫번째 페이지    
    BEGIN
        SET @StrSQL =
            'SELECT TOP ' + STR(@PageSize) + '
                NoticeID, TypeID, NoticeNo, Title, Contents, WriterID, WriteDate, NoticeDate, Hit, IsShow, @TotalRow as TotalRow' +
            '  FROM dbo.Notice WHERE TypeID=@TypeID ' + @SearchPart  + ' ORDER BY TypeID, NoticeNo DESC'
    END
    ELSE IF @PageNo >= @LastPage AND @LastPageRow > 0         -- 마지막 페이지
    BEGIN
        SET @StrSQL = '
             SELECT * FROM (
                 SELECT TOP ' + STR(@LastPageRow) + ' NoticeID, TypeID, NoticeNo, Title, Contents, WriterID, WriteDate, NoticeDate,Hit, IsShow, @TotalRow as TotalRow' +
                '  FROM dbo.Notice WHERE TypeID=@TypeID ' + @SearchPart + ' ORDER BY TypeID, NoticeNo ASC
            ) AS B ORDER BY TypeID, NoticeNo DESC'   
    END
    ELSE                                     -- 일반 페이지
    BEGIN
        SET @StrSQL = 'SELECT * FROM ( SELECT TOP ' + STR(@PageSize) + ' * FROM (' +
            ' SELECT TOP ' + STR(@PageNo*@PageSize) + ' NoticeID, TypeID, NoticeNo, Title, Contents, WriterID, WriteDate, NoticeDate,Hit, IsShow, @TotalRow as TotalRow ' +
            ' FROM dbo.Notice WHERE TypeID=@TypeID ' + @SearchPart + '  ORDER BY TypeID, NoticeNo DESC) AS B ORDER BY TypeID, NoticeNo  ASC) as C' +
            ' ORDER BY TypeID, NoticeNo DESC'
    END
    EXEC sp_executesql @StrSQL, @Param, @TypeID, @IsShow, @SearchKey, @SearchString,@TotalRow output



반응형

'연구개발 > DBA' 카테고리의 다른 글

동적쿼리 값 반환  (0) 2012.01.02
Deadlock 모니터링 하기  (0) 2011.12.06
데이터베이스 옵션들  (0) 2011.11.22
SQL Server 에러 로그 확인 및 관리 방법  (0) 2011.11.14
[DMV] Look for overall Memory Consumption  (0) 2011.11.04
반응형

자동 옵션

 

AUTO_CLOSE:

ON 이면 마지막 사용자의 연결이 끝날 경우 데이터베이스를 종료하고 데이터베이스가 사용하던 리소스를 해제합니다.

그러나 다시 사용자가 데이터베이스에 연결하면 데이터베이스가 시작됩니다.

이 옵션은 일반적으로 OFF로 구성하며 클라이언트 컴퓨터에서 SQL Server를 운영하거나 SQL Server Express 버전을

사용하는 경우에만 ON으로 설정합니다.


AUTO_CREATE_STATISTICS:

ON 이면 쿼리 최적화에 필요한 통계 중 누락된 통계를 쿼리 최적화 동안 자동으로 생성합니다.

기본값은 ON이며 OFF로 구성하면 주기적으로 데이터베이스 통계를 직접 생성해야만 합니다.

통계는 쿼리 최적화 프로세스가 실행 계획을 만들 때 중요한 정보로 사용됩니다.

따라서 쿼리 최적화 프로세스는 이 옵션의 설정 값과 상관없이 항상 이 설정을 ON으로 간주하고 동작합니다.

이 옵션은 데이터베이스 성능과 밀접한 관계가 있으므로 ON으로 설정하는 것을 권장합니다.

 

AUTO_UPDATE_STATISTICS:

기본값은 ON이며 쿼리 최적화에 필요한 통계 중 날짜가 지난 통계 정보를 쿼리 최적화 동안 자동으로 갱신합니다.

OFF로 구성하면 통계를 수동으로 갱신해야 합니다.

제대로 갱신되지 못한 잘못된 통계 정보는 데이터베이스 성능에 나쁜 영향을 끼칠 수 있습니다.

 

AUTO_SHRINK:

이 옵션을 ON으로 설정하면 주기적으로 데이터베이스의 데이터 파일과 로그 파일을 자동으로 축소합니다.

이 축소 작업은 파일에서 사용하지 않는 공간이 전체 공간의 25 %를 초과할 때 수행됩니다.

OFF로 설정하면 SQL Server가 주기적으로 사용되지 않는 공간을 검사할 때 해당 데이터베이스 파일을 축소하지 않습니다.


데이터베이스 가용성 옵션

 

OFFLINE, ONLINE, EMERGENCY:

기본값은 ONLINE이며 데이터베이스가 정상적으로 동작함을 의미합니다.

 

OFFLINE으로 설정하면 데이터베이스는 종료되고 SSMS도구의 개체 탐색기에서 빨간색 화살표 아이콘과 함께 오프라인으로

표시됩니다. 이 상태에서는 데이터베이스를 수정하거나 접근할 수 없습니다.

 

EMERGENCY로 지정되면 데이터베이스가 읽기 전용으로 표시되고 로깅 설정이 해제되고 sysadmin 역할의 구성원만

해당 데이터베이스에 연결할 수 있습니다.

이 옵션은 손상된 로그 파일로 인해 주의 대상으로 표시된 데이터베이스 등에 대한 문제 해결을 위해 사용됩니다.


READ_ONLY, READ_WRITE:

기본값은 READ_WRITE이며 데이터에 대한 읽기/쓰기 작업이 가능합니다.

 

READ_ONLY로 지정하면 해당 데이터베이스는 읽기 작업만 수행할 수 있으며 SSMS의 개체 탐색기에서 읽기 전용으로

나타납니다.

 

SINGLE_USER, MULTI_USER, RESTRICTED_USER:

기본값은 MULTI_USER이며 권한이 있는 사용자는 모두 데이터베이스에 연결할 수 있습니다.

 

SINLE_USER를 지정하면 한 사용자만 데이터베이스에 연결할 수 있습니다.

이 설정은 보통 데이터베이스의 상태를 변경하거나 설정을 변경하는 등의 관리 작업을 수행하는 경우에 유용합니다.

이 옵션을 설정할 때 데이터베이스에 다른 사용자들이 연결되어 있다면 모든 사용자의 연결이 끊어질 때까지

ALTER DATABASE 문은 차단됩니다.

따라서 이 경우에는 ALTER DATABASE 문에 WITH Rollback Immediate 등의 절을 추가해서 사용하는 것이 좋습니다.

데이터베이스에 이 옵션을 ON으로 설정하기 전에 AUTO_UPDATE_STATISTICS_ASYNC 옵션이 OFF로 설정되어 있는지

확인합니다.

이 옵션이 ON으로 설정되어 있다면 통계 업데이트를 수행하는 스레드가 백그라운드 상태로 데이터베이스에 연결되어

있으므로 단일 사용자 모드로는 데이터베이스에 접근할 수 없습니다.

 

RESTRICTED_USER를 지정하면 sysadmin, db_owner 및 db_creator 역할의 구성원만 연결 수에 상관없이 데이터베이스에

연결할 수 있습니다.

이 설정은 보통 개발 DB나 테스트 DB 처럼 특정한 사용자만 연결하고 일반 사용자의 연결을 제한하기 원할 때 유용합니다.

 

날짜 상관 관계 최적화 옵션

 

DATE_CORRELATION_OPTIMIZATION:

이 설정은 date나 datetime 데이터 형식의 열이 상호 관련된 두 테이블 사이에서 동등 조인을 수행하고 날짜 조건을

지정하는 쿼리에 대한 성능을 향상시키기 위해 사용합니다.

이 설정을 ON으로 지정하면 date나 datetime 열이 있는 조인된 두 테이블 사이에서 상관 관계 통계를 유지합니다.

이 설정의 기본값은 OFF입니다.


외부 액세스 옵션

 

DB_CHAINING:

이 옵션은 데이터베이스 사이의 소유권 체인을 지정하기 위한 값으로 기본값은 OFF입니다.

이 옵션을 ON으로 지정하면 해당 데이터베이스는 데이터베이스 간 소유권 체인의 원본이나 대상으로 소유권 체인에

참여할 수 있습니다.

 

TRUSTWORTHY:

이 옵션을 ON으로 지정하면 가장된 사용자 컨텍스트를 통해 데이터베이스 외부의 리소스에 접근할 수 있도록 해줍니다.

기본값은 msdb 데이터베이스를 제외한 모든 데이터베이스 대해 OFF로 설정되어 있으며 이 상태에서는 가장 컨텍스트를

사용해서 데이터베이스의 외부 리소스에 접근할 수 없습니다.


매개 변수화 옵션


PARAMETERIZATION:

이 옵션은 데이터베이스의 쿼리를 매개 변수화하기 위한 설정으로 단순 매개 변수화와 강제 매개 변수화 프로세스를

구성할 수 있습니다.


복구 옵션

 

RECOVERY:

이 옵션은 매우 중요한 옵션이나 백업 복구 과정에 필수적입니다.


TORN_PAGE_DETECTION:

이 옵션이 ON이면 데이터베이스 엔진에서 완료되지 않은 페이지를 검색할 수 있습니다.

그러나 이 옵션은 다음 버전의 SQL Server에서 제거될 수 있으므로 가능하면 이 옵션 대신 PAGE_VERIFY 옵션을

사용하기를 권장합니다.

 

PAGE_VERIFY:

이 옵션은 전원 오류나 하드웨어 오류 등으로 인해 페이지를 디스크에 기록할 때 발생하는 손상된 데이터베이스의 페이지를

확인합니다.

이 옵션은 다음의 3가지 값을 가지며 SQL Server 2005 및 SQL Server 2008에서의 기본값은 CHECKSUM입니다.

 

   CHECKSUM: 이 옵션 설정은 페이지를 디스크에 기록할 때 전체 페이지의 내용에 대한 체크섬을 계산하여 페이지 헤더에

   저장하도록 합니다.

   SQL Server가 해당 페이지를 읽을 경우 다시 체크섬을 계산하여 페이지 헤더에 저장된 값과 비교하여 두 값이 일치하지 

   않으면 체크섬 오류 로그인 824 로그를 SQL Server 오류 로그와 Windows 이벤트 로그에 기록합니다.

   이러한 체크섬 오류는 I/O 경로 문제가 발생했음을 나타냅니다.

 

   TORN_PAGE_DETECTION:

   이 옵션은 SQL Server 이전 버전에서 제공하던 TORN_PAGE_DETECTION 옵션과 비슷합니다.

   SQL Server의 한 I/O는 8KB입니다.

   반면에 Windows의 한 I/O는 512 바이트입니다.

   따라서 SQL Server가 한 I/O, 즉 8KB의 한 페이지를 디스크에 쓸 때 Windows 는 페이지의 각 512 바이트 섹터에 대해 특정

   비트를 데이터베이스 페이지 헤더에 저장합니다.

   디스크에서 페이지를 읽게 되면 페이지 헤더에 저장된 비트와 실제 페이지 섹터 정보를 비교합니다.

   이 값이 일치하지 않으면 페이지의 일부분만 디스크에 기록된 것이며 이를 조각난 페이지(TORN PAGE)라고 합니다.

   이 경우 824 오류 메시지가 SQL Server 오류 로그와 Windows 이벤트 로그에 기록됩니다.

   이러한 조각난 페이지는 디스크에 기록을 완료하지 못할 경우에도 발생하지만 다른 I/O 경로 오류로 인해서도

   발생할 수 있습니다.

 

   NONE:

   이 옵션을 지정하면 페이지를 기록할 경우에 CHECKSUM이나 TORN_PAGE_DETECTION 값을 생성하지 않으며

   페이지를 읽을 경우에도 이들을 확인하지 않습니다.

반응형

'연구개발 > DBA' 카테고리의 다른 글

Deadlock 모니터링 하기  (0) 2011.12.06
페이징 쿼리  (0) 2011.11.29
SQL Server 에러 로그 확인 및 관리 방법  (0) 2011.11.14
[DMV] Look for overall Memory Consumption  (0) 2011.11.04
[DMV] CPU bottleneck detection  (0) 2011.11.04
반응형
SQL Server의 현재 상태를 가장 정확하고 빠르게 파악할 수 있는 SQL Server 에러 로그를 가독하기 좋은 형태로 관리하는 방법을 소개합니다.

아울러 이를 별도의 테이블로 관리할 수 있는 방법을 설명합니다.


다음 방법을 순서대로 따라 해 보세요.
  1. SQL Server 에러 로그 읽기
    1. SQL Server Management Studio(SSMS) 실행하기

      [시작], [모든 프로그램], [Micro SQL Server 2005](또는 Micro SQL Server 2008이나 2008 R2), [SQL Server Management Studio]를 차례대로 클릭하여 SQL Server Management Studio를 실행하세요.

      그림 확대

    2. 데이터베이스 연결하기

      연결 정보(서버 이름 또는 IP Address 로그인 정보)를 입력하여 조회하고자 하는 서버와 연결하세요.


    3. sp_readerrolog 구문 실행


      이 때, 실행 버튼(F5 혹은 CTRL+E)을 누르기 전에 [텍스트로 결과 표시]를(
      )선택하거나 CTRL+T를 누르세요.

      이후 실행하게 되면 아래와 같이 가독하기 좋은 형태로 에러 로그를 확인할 수 있습니다.

      그림 확대


      서버의 정보(OS 및 SQL Sever의 버전, 서버 이름), master 데이터베이스 및 에러 로그 파일의 위치 및 활성화된 Trace Flag의 정보도 확인할 수 있습니다.

      스크롤바를 이동하여 현재 시점에서 주목할 만한 메시지는 없는지 확인하도록 합니다.

  2. SQL Server 에러 로그 관리하기

    SQL Server 에러 로그는 기본적으로 총 7개의 파일로 관리 됩니다. 서비스가 재시작 될 때 마다 Rollover 되며, 기본 파일의 수를 넘어서는 로그는 사라집니다.
    따 라서 예기치 않은 이유로 SQL Server가 여러 번 반복적으로 재시작 되면 문제 시점의 로그를 확보할 수 없게 될 수도 있습니다. 이를 예방하기 위해 기본적으로 관리되는 7개의 파일 보다 더 많은 수의 파일로 관리되도록 조정할 수 있습니다.
    여기서는 파일의 수를 늘리는 것이 아닌 에러 로그를 테이블로 관리하는 방법을 소개합니다. 이 내용은 How to Archive your SQL Errorlogs into a Table에서도 확인할 수 있습니다.

    수 많은 로그인 실패 메시지 등이 로깅 되면서 하나의 에러 로그 파일의 크기가 매우 커지게 되는 경우가 발생할 수 있습니다.



    이러한 경우, 에러 로그를 로그 뷰어나 sp_readerrorlog 구문으로 읽기를 시도하면 오랜 시간이 걸릴 수 있으므로 내가 원하는 시간에 대한 로그 파악이 어려울 수도 있습니다.

    이 때 활용할 수 있는 방법은 다음과 같습니다.
    1. SQL Server Errorlog 및 Agent Log 관리용 테이블 생성

      IF  NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[MS_SQLERRORLOG]') AND type in (N'U'))
      BEGIN
      CREATE TABLE [dbo].[MS_SQLERRORLOG](
          [LogDate] [datetime] NULL,
          [ProcessInfo] [varchar](10) NULL,
          [Text] [varchar](max) NULL
      ) ON [PRIMARY]
      END
      GO
      
      
      IF  NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[MS_SQLAGENTLOG]') AND type in (N'U'))
      BEGIN
      CREATE TABLE [dbo].[MS_SQLAGENTLOG](
          [LogDate] [datetime] NULL,
          [ProcessInfo] [varchar](10) NULL,
          [Text] [varchar](max) NULL
      ) ON [PRIMARY]
      END
      GO
    2. 현재 시점까지의 Errorlog 저장하기
      INSERT INTO MS_SQLERRORLOG
      EXEC ('sp_readerrorlog')
      GO
      
      EXEC msdb.dbo.sp_cycle_errorlog
      GO
    3. 현재 시점까지의 Agent Log 저장하기(에이전트 서비스가 반드시 동작 중이어야 함)
      INSERT INTO MS_SQLAGENTLOG
      EXEC ('sp_readerrorlog -1, 2')
      GO
      
      EXEC msdb.dbo.sp_cycle_agent_errorlog
      GO
    4. 테이블 생성 후 2), 3)의 방법을 주기적으로 수행하여 SQL Server 로그를 테이블로 이관하여 관리하면, Log Date 및 ProcessInfo 등에 따라서 원하는 내용의 로그를 보다 빠르게 확인할 수 있으며 아울러 에러 로그의 크기가 커져서 디스크의 공간을 과도하게 차지하는 것을 예방할 수 있습니다.



다음 내용을 참고 하세요.
반응형

'연구개발 > DBA' 카테고리의 다른 글

페이징 쿼리  (0) 2011.11.29
데이터베이스 옵션들  (0) 2011.11.22
[DMV] Look for overall Memory Consumption  (0) 2011.11.04
[DMV] CPU bottleneck detection  (0) 2011.11.04
[DMV] 메모리 버퍼 사용량 조회하기  (0) 2011.11.04
반응형
-- Look for overall Memory Consumption

-- find consumers with that account for more than 5% of the memory consumption thourgh SPA OR MPA

-- sys.dm_os_memory_clerks

declare @total_alloc bigint

declare @tab table (

             type nvarchar(128) collate database_default

             ,allocated bigint

             ,vertual_res bigint

             ,virtual_com bigint

             ,awe bigint

             ,shared_res bigint

             ,shared_com bigint

             ,topFive nvarchar(128)

             ,grAND_total bigint

);

 

SELECT  @total_alloc = sum(single_pages_kb + multi_pages_kb + (CASE WHEN type <> 'MEMORYCLERK_SQLBUFFERPOOL' THEN virtual_memory_committed_kb ELSE 0 END) + shared_memory_committed_kb)

FROM sys.dm_os_memory_clerks

 

--print 'Total allocated, except BPool: ' + CAST(@total_alloc AS varchar(10)) + ' Kb'

 

insert into @tab

SELECT  type

,            sum(single_pages_kb + multi_pages_kb) AS allocated

,            sum(virtual_memory_reserved_kb) AS vertual_res

,            sum(virtual_memory_committed_kb) AS virtual_com

,            sum(awe_allocated_kb) AS awe

,            sum(shared_memory_reserved_kb) AS shared_res

,            sum(shared_memory_committed_kb) AS shared_com

,            case  when  ((sum(single_pages_kb + multi_pages_kb + (CASE WHEN type <> 'MEMORYCLERK_SQLBUFFERPOOL' THEN virtual_memory_committed_kb ELSE 0 END) + shared_memory_committed_kb))/(@total_alloc + 0.0)) >= 0.05

                             then type

                             else 'Other'

             end AS topFive

,            (sum(single_pages_kb + multi_pages_kb + (CASE WHEN type <> 'MEMORYCLERK_SQLBUFFERPOOL' THEN virtual_memory_committed_kb ELSE 0 END) + shared_memory_committed_kb)) AS grAND_total

FROM sys.dm_os_memory_clerks

GROUP BY type

ORDER BY (sum(single_pages_kb + multi_pages_kb + (CASE WHEN type <> 'MEMORYCLERK_SQLBUFFERPOOL' THEN virtual_memory_committed_kb ELSE 0 END) + shared_memory_committed_kb)) DESC

 

SELECT  * FROM @tab

반응형

'연구개발 > DBA' 카테고리의 다른 글

데이터베이스 옵션들  (0) 2011.11.22
SQL Server 에러 로그 확인 및 관리 방법  (0) 2011.11.14
[DMV] CPU bottleneck detection  (0) 2011.11.04
[DMV] 메모리 버퍼 사용량 조회하기  (0) 2011.11.04
[DMV] Tempdb space  (0) 2011.11.04
반응형

-- CPU bottleneck detection

-- aggregate CPU usage BY cached plans with SQL text

SELECT

             total_cpu_time,

             total_execution_count,

             number_of_statements,

             s2.text

FROM

             (SELECT TOP 50

                           SUM(qs.total_worker_time) AS total_cpu_time,

                           SUM(qs.execution_count) AS total_execution_count,

                           COUNT(*) AS  number_of_statements,

                           qs.sql_handle

             FROM

                           sys.dm_exec_query_stats AS qs

             GROUP BY qs.sql_handle

             ORDER BY SUM(qs.total_worker_time) DESC) AS stats

             CROSS APPLY sys.dm_exec_sql_text(stats.sql_handle) AS s2
반응형

'연구개발 > DBA' 카테고리의 다른 글

SQL Server 에러 로그 확인 및 관리 방법  (0) 2011.11.14
[DMV] Look for overall Memory Consumption  (0) 2011.11.04
[DMV] 메모리 버퍼 사용량 조회하기  (0) 2011.11.04
[DMV] Tempdb space  (0) 2011.11.04
[DMV] Top I/O Queries  (0) 2011.11.04
반응형

1. DMV 쿼리

 

현재 데이터베이스 서버에서 사용하고 있는 버퍼를 개체 별로 조회하기 데이터베이스

SELECT

             b.database_id,

             db=db_name(b.database_id)

             ,p.object_id

             ,object_name(p.object_id) as objname

             ,p.index_id

             ,buffer_count=count(*)

FROM sys.allocation_units a,

          sys.dm_os_buffer_descriptors b,

          sys.partitions p

WHERE a.allocation_unit_id = b.allocation_unit_id

             and a.container_id = p.hobt_id

             and b.database_id = db_id() -- 현재의 데이터베이스

GROUP BY b.database_id,p.object_id, p.index_id

ORDER BY buffer_count desc

GO

 

 

2. 사용 목적

서버의 버퍼 할당량을 개체 별로 조회할 때 이용합니다. 메모리를 많이 차지하고 있는 개체 및 개체의 인덱스 정보를 파악할 수 있습니다.

 

 

3. 결과

 

 

 

4. 결과 정의

 

Column

Description

database_id

데이터베이스 ID 입니다. sys.databases 에서 확인할 있습니다.

db

데이터베이스 명입니다.

object_id

인덱스가 있는 테이블 또는 뷰의 ID 입니다. sys.objects 에서 개체에 대한 ID 확인할 있습니다.

objname

개체 명입니다.

index_id

인덱스 ID입니다.

buffer_count

해당 개체의 데이터 페이지 또는 인덱스 페이지가 차지하고 있는 버퍼의 개수를 나타냅니다.

 

반응형

'연구개발 > DBA' 카테고리의 다른 글

[DMV] Look for overall Memory Consumption  (0) 2011.11.04
[DMV] CPU bottleneck detection  (0) 2011.11.04
[DMV] Tempdb space  (0) 2011.11.04
[DMV] Top I/O Queries  (0) 2011.11.04
[DMV] Inefficient Query  (0) 2011.11.04
반응형

-- tempdb space

SELECT  SUM (user_object_reserved_page_count) * 8 AS user_objects_kb,

                           SUM (internal_object_reserved_page_count) * 8 AS internal_objects_kb,

                           SUM (version_store_reserved_page_count) * 8  AS version_store_kb,

                           SUM (unallocated_extent_page_count) * 8 AS freespace_kb

FROM     sys.dm_db_file_space_usage

WHERE   database_id = 2
반응형

'연구개발 > DBA' 카테고리의 다른 글

[DMV] CPU bottleneck detection  (0) 2011.11.04
[DMV] 메모리 버퍼 사용량 조회하기  (0) 2011.11.04
[DMV] Top I/O Queries  (0) 2011.11.04
[DMV] Inefficient Query  (0) 2011.11.04
[DMV] Plans with large CPU consumption  (0) 2011.11.04
반응형

-- top 5 I/O

SELECT top 5

             (total_logical_reads/execution_count) AS avg_logical_reads,

             (total_logical_writes/execution_count) AS avg_logical_writes,

             (total_physical_reads/execution_count) AS avg_phys_reads,

             execution_count,

             statement_start_offset AS stmt_start_offset,

             sql_text.text,

             query_plan.query_plan

FROM     sys.dm_exec_query_stats a

             CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sql_text

             CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS query_plan

ORDER BY (total_logical_reads + total_logical_writes) DESC
반응형

'연구개발 > DBA' 카테고리의 다른 글

[DMV] 메모리 버퍼 사용량 조회하기  (0) 2011.11.04
[DMV] Tempdb space  (0) 2011.11.04
[DMV] Inefficient Query  (0) 2011.11.04
[DMV] Plans with large CPU consumption  (0) 2011.11.04
[DMV] Excessive compiles/recompiles  (0) 2011.11.04
반응형

-- inefficient query

SELECT

    highest_cpu_queries.plan_handle,

    highest_cpu_queries.total_worker_time,

    q.dbid,

    q.objectid,

    q.number,

    q.encrypted,

    q.[text]

FROM

    (SELECT top 50

        qs.plan_handle,

        qs.total_worker_time

    FROM

        sys.dm_exec_query_stats qs

    ORDER BY qs.total_worker_time DESC) AS highest_cpu_queries

    CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS q

ORDER BY highest_cpu_queries.total_worker_time DESC
반응형

'연구개발 > DBA' 카테고리의 다른 글

[DMV] Tempdb space  (0) 2011.11.04
[DMV] Top I/O Queries  (0) 2011.11.04
[DMV] Plans with large CPU consumption  (0) 2011.11.04
[DMV] Excessive compiles/recompiles  (0) 2011.11.04
[DMV] Active sessions, Sleeping and Background  (0) 2011.11.04
반응형

-- Plans with large CPU consumption

-- looking for Sort AND Hash Match IN plans

SELECT TOP 10

             bucketid,

             refcounts,

             usecounts,

             size_in_bytes,

             cacheobjtype,

             dbid, objectid,

             query_plan

FROM

             sys.dm_exec_cached_plans

             CROSS APPLY sys.dm_exec_query_plan(plan_handle)

WHERE

             cast(query_plan AS nvarchar(max)) LIKE '%Sort%'

             OR cast(query_plan AS nvarchar(max)) LIKE '%Hash Match%'

ORDER BY size_in_bytes desc
반응형
반응형

-- Excessive compiles/recompiles

SELECT top 25

             sql_text.text,

             sql_handle,

             plan_generation_num,

             execution_count,

             dbid,

             objectid

FROM sys.dm_exec_query_stats a

             CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sql_text

WHERE plan_generation_num > 1

ORDER BY plan_generation_num DESC
반응형
반응형

-- output information for active sessions, sleeping AND background

-- the output is similar to what you get FROM sys.sysprocesses

SELECT

             es.session_id

             , case when es.status IN ('sleeping', 'background') then 'Sleep/Bkgnd' else 'Active' end AS SessStatus

             , db_name(er.database_id) AS DBName

             , es.login_name

             , er.blocking_session_id

             , er.wait_time

             , (case

                           when er.wait_time = 0 then ''

                           when er.wait_time <> 0 then er.last_wait_type

             end) AS WaitOn

             , es.cpu_time + er.cpu_time AS TotalCPU

             , es.cpu_time AS SessCPU

             , (es.reads + es.writes) AS SessAggIO

             , es.memory_usage

             , er.cpu_time AS ReqCPU

             , (er.reads + er.writes) AS ReqAggIO

             , er.open_transaction_count

             , er.status

             , es.host_name

             , es.program_name

             , er.commAND

             , (SELECT SUBSTRING(text, statement_start_offset/2, (case when statement_end_offset = -1 then len(convert(nvarchar(max), text)) * 2 else statement_end_offset end -statement_start_offset)/2) FROM sys.dm_exec_sql_text(sql_handle)) AS QueryText

FROM

             sys.dm_exec_sessions AS es JOIN

             sys.dm_exec_requests AS er on es.session_id = er.session_id

WHERE

             es.is_user_process = 1

ORDER by

             es.session_id

 

-- info for sleeping sessions that do NOT have associated requests

SELECT

             es.session_id

             , es.login_name

             , es.cpu_time AS SessCPU

             , (es.reads + es.writes) AS SessAggIO

             , es.memory_usage

             , es.host_name

             , es.program_name

FROM

             sys.dm_exec_sessions AS es

WHERE

             lower(es.status) = 'sleeping'

             AND es.session_id NOT IN (SELECT session_id FROM sys.dm_exec_requests)

             AND es.is_user_process = 1

ORDER by

             es.session_id

go
반응형
반응형

 

1. DMV 쿼리

 

AdventureWorks 데이터베이스의 Sales.SalesOrderDetail 테이블에 있는 인덱스의 조각화 정보

SELECT

             a.database_id,

             a.object_id,

             a.index_id,

             name,

             avg_fragmentation_in_percent

FROM sys.dm_db_index_physical_stats (DB_ID(), object_id('Sales.SalesOrderDetail'),NULL, NULL, NULL) AS a

    JOIN sys.indexes AS b ON a.object_id = b.object_id AND a.index_id = b.index_id

WHERE a.database_id = db_id()

ORDER BY a.object_id

GO 

 

 

2. 사용 목적

지정된 테이블에 있는 인덱스들에 대한 조각화 정도를 조회하는 DMV 입니다. 인덱스의 조각화가 심할 경우, 해당 인덱스를 참조하는 쿼리에서 불필요하게 많은 I/O가 발생할 수 있습니다. 자주 사용되는 테이블이나 인덱스 조각화가 심한 테이블일 경우, 주기적으로 인덱스 조각화를 제거하는 관리 작업을 수행해 줄 필요가 있습니다.

 

 

3. 결과

 

 

 

4. 결과 정의

 

Column

Description

database_id

데이터베이스 ID 입니다. sys.databases 에서 확인할 있습니다.

object_id

인덱스가 있는 테이블 또는 뷰의 ID 입니다. sys.objects 에서 개체에 대한 ID 확인할 있습니다.

index_id

인덱스 ID입니다.

name

인덱스 입니다.

avg_fragmentation_in_percent

인덱스의 조각화 정도(%) 나타냅니다. 0 가까울수록 좋은 상태를 나타내지만, 대게 0~10% 정도의 값이면 적당합니다.

조각화가 많이 발생한 경우, 인덱스 조각화 제거 작업을 수행해야 합니다.

 

 

5. 참고 사항 추가 설명

1) SQL Server 2000 경우,

 

                           DBCC SHOWCONTIG(<테이블 >, <인덱스 >)

 

                   이용해서 인덱스의 조각화 정도를 파악할 있습니다.
반응형
반응형

SELECT

        t1.resource_type,

        t1.resource_database_id,

        t1.resource_associated_entity_id,

        t1.request_mode,

        t1.request_session_id,

        t2.blocking_session_id

    FROM sys.dm_tran_locks as t1

    INNER JOIN sys.dm_os_waiting_tasks as t2

        ON t1.lock_owner_address = t2.resource_address;
반응형
반응형

--Simple

SELECT top 10 *

FROM sys.dm_os_wait_stats

WHERE wait_type NOT IN ('CLR_SEMAPHORE','LAZYWRITER_SLEEP','RESOURCE_QUEUE','SLEEP_TASK','SLEEP_SYSTEMTASK','WAITFOR')

ORDER BY wait_time_ms DESC

GO

 

--Detail

declare @totalWait bigint

declare @totalSignalWait bigint

declare @totalResourceWait bigint

 

SELECT

             @totalWait = sum([wait_time_ms]),

             @totalSignalWait = sum([signal_wait_time_ms])

FROM

             sys.dm_os_wait_stats

WHERE

             [wait_type] NOT IN ('CLR_SEMAPHORE','LAZYWRITER_SLEEP','RESOURCE_QUEUE','SLEEP_TASK','SLEEP_SYSTEMTASK','WAITFOR')

 

SELECT @totalResourceWait = @totalWait - @totalSignalWait

 

SELECT top 10

             wait_type,

             waiting_tasks_count,

             wait_time_ms-signal_wait_time_ms AS resource_wait_ms,

             cast(100*(wait_time_ms - signal_wait_time_ms) / @totalResourceWait AS numeric(20,1)) AS resource_wait_percent,

             signal_wait_time_ms,

             cast(100*signal_wait_time_ms / @totalSignalWait AS numeric(20,1)) AS signal_wait_percent,

             wait_time_ms,

             cast(100*wait_time_ms / @totalwait AS numeric(20,1)) AS wait_time_percent

FROM

             sys.dm_os_wait_stats

WHERE

             [wait_type] NOT IN ('CLR_SEMAPHORE','LAZYWRITER_SLEEP','RESOURCE_QUEUE','SLEEP_TASK','SLEEP_SYSTEMTASK','WAITFOR')

ORDER BY 4 DESC

GO
반응형

'연구개발 > DBA' 카테고리의 다른 글

[DMV] 테이블의 인덱스 조각화 정도 조회하기  (0) 2011.11.04
[DMV] Blocking 정보 표시  (0) 2011.11.04
SS2000 - 현재 캐시된 내용 조회하기  (0) 2011.10.08
재귀쿼리  (0) 2011.09.26
암호화  (0) 2011.09.22
반응형
SELECT
             c.name                            AS DBName,
             b.name                            AS ObjectName,
             a.objtype,
             a.cacheobjtype,
             a.refcounts,
             a.usecounts,
             a.pagesused,
             a.sqlbytes,
             a.sql
FROM master..syscacheobjects AS a
             LEFT JOIN master..sysobjects AS b
                ON a.objid = b.id
             LEFT JOIN master..sysdatabases AS c
                ON a.dbid = c.dbid
ORDER BY DBName, ObjectName, a.objtype

반응형

'연구개발 > DBA' 카테고리의 다른 글

[DMV] Blocking 정보 표시  (0) 2011.11.04
[DMV] Wait Resources List  (0) 2011.11.04
재귀쿼리  (0) 2011.09.26
암호화  (0) 2011.09.22
datetime과 smalldatetime과 unixtime의 변환  (0) 2011.09.22
반응형
CREATE TABLE Department
(
    dept_code int primary key,
    dept_name varchar(20),
    parent_dept int REFERENCES Department
)
GO

BEGIN
    INSERT Department VALUES (1000, '(주)ABC', null)
    INSERT Department VALUES (1001, '관리본부', 1000)
    INSERT Department VALUES (1002, '건설사업본부', 1000)
    INSERT Department VALUES (1003, '경리팀', 1001)
    INSERT Department VALUES (1004, '업무팀', 1001)
    INSERT Department VALUES (1005, '자재팀', 1001)
    INSERT Department VALUES (1006, '공무팀', 1002)
    INSERT Department VALUES (1007, '공사팀', 1002)
    INSERT Department VALUES (1008, '설계팀', 1002)
END

SELECT * FROM Department;

CREATE FUNCTION dbo.udf_listDept
(
    @parent_dept as int
)
RETURNS @tree TABLE
(
    dept_code    int,
    dept_name    varchar(20),
    parent_dept    int
)
AS
BEGIN
    INSERT INTO @tree
    SELECT * FROM Department WHERE dept_code = @parent_dept

    DECLARE @curdept as int

    SELECT @curdept = MIN(dept_code) FROM Department
    WHERE parent_dept = @parent_dept

    WHILE @curdept IS NOT NULL
    BEGIN
        INSERT INTO @tree
        SELECT * FROM udf_listDept(@curdept)

        SELECT @curdept = MIN(dept_code) FROM Department
        WHERE parent_dept = @parent_dept AND dept_code > @curdept
    END
    RETURN
END

SELECT * FROM dbo.udf_listDept(1002)
반응형
반응형
MSSQL에서는 아래와 같은 암호화를 지원했었다.
  1. PwdEncrypt - 암호화
    PwdEncrypt('암호화문자')
    ex) INSERT INTO members(user_id, password) VALUES('myid', PwdEncrypt('mypwd'))
  2. PwdCompare - 비교
    PwdCompare('비교대상문자', '암호화 된 문자')
    ->양쪽이 같으면 1을 리턴 다르면 0 리턴, 둘중하나가 NULL 이면 NULL 을 리턴
    ex) SELECT PwdCompare('1234', password) FROM members WHERE user_id = 'myid'
하지만 PwdEncrypt는 오래된 암호화 모듈이라 차후 버전에서는 사용하지 않을 수 있다.
(http://msdn.microsoft.com/ko-kr/library/dd822791.aspx)

대신 HashBytes의 사용을 권고한다. (http://msdn.microsoft.com/ko-kr/library/ms174415.aspx)
반응형
반응형
b에 시간에 대해 저장할 때 datetime과 unixtime 두 가지 방식 중 하나를 이용하여 저장한다.

다음과 같은 query가 datetime 컬럼에 대해 실행되면 어떻게 될까?
1.INSERT 테이블 (날짜컬럼) values(0)

위의 경우 datetime 형식 컬럼에는 '1900-01-01 00:00:00.000'이 저장된다.
만약 int값을 0이 아닌 값으로 실행하면 어떻게 될까?
1.INSERT 테이블 (날짜컬럼) values(1)

위의 경우 datatime 형식 컬럼에는 '1900-01-02 00:00:00.000'이 저장된다.
즉 숫자형의 값을 datetime 컬럼에 입력하면 '1900-01-01 00:00:00.000'을 기준으로 day가 증가 또는 감소한 값이 저장된다.

unixtime은 '1970-01-01 00:00:00'으로 부터 초/분단위로 데이터를 저장하는 형식이지만 특정한 데이터 타입으로 존재하는 것은 아니다.
따라서 초단위 이하까지의 디테일한 데이터가 필요하지 않을 경우 위의 특성을 이용하여 분단위 저장을 하는 것도 나쁘지 않다.

unixtime으로 초/단위 저장을 할 경우 아래와 같이 저장을 한다.
1.INSERT 테이블 VALUES ('[1970-01-01 00:00:00.000 으로 부터 지난 초/분 숫자])

이러한 unixtime으로 저장을 하게 되면 4byte의 값으로 8byte의 datetime의 값을 저장할 수 있다는 장점이 있다.
1970-01-01 00;00:00.000분으로 부터 지난 초/분을 구하려면 datediff 함수를 사용하면 된다.

1.select datediff(second, '1970-01-01 00:00:00.000', [구하려는날짜])
2.select datediff(minute, '1970-01-01 00:00:00.000', [구하려는날짜])

이렇게 unixtime으로 변경된 시간을 다시 datetime 형식으로 구하려면 dateadd 함수를 사용하여 기준이 되는 날짜로 부터 더해진 초/분을 계산하면 된다.
1.select dateadd(second, [unixtime 값], '1970-01-01 00:00:00.000')
2.select dateadd(minute, [unixtime 값], '1970-01-01 00:00:00.000')
반응형
반응형
어떤 테이블의 varchar 타입 컬럼을 검색하는 SP를 작성할 경우 아래와 같이 작성하곤 한다.

1.CREATE PROCEDURE [dbo].[searchA]
2.@searchColumnA NVARCHAR(12)
3.AS
4.SET NOCOUNT ON
5.SELECT * FROM A WITH (READUNCOMMITTED) WHERE columnA = @searchColumnA

이 쿼리를 직접 테스트 할 때 이상없더라도 SP로 호출하면 급격히 느려질 수 있다.

이유는 varchar로 된 고정 길이의 columnA을 검색하기 위해 입력한 @searchColumnA에 대해 매번 테이블을 조회하는 경우 CONVERT 과정이 더해지기 때문이다.

이는 데이터 형식의 선행 규칙에 의해 이루어지며 자세한 내용은 아래 링크를 통해 알 수 있다.
http://msdn.microsoft.com/ko-kr/library/ms190309(SQL.90).aspx

문제는 검색에 사용된 nvarchar 형식보다 varchar형식의 선행 규칙 우선순위가 낮으므로 where 구문의 왼쪽 조건절에 대한 convert가 일어나게 되어 해당 테이블의 열이 많으면 많을 수록 검색시 convert로 인한 부하가 증가하게 되는 것이다.
1.SELECT * FROM A WITH (READUNCOMMITTED) WHERE CONVERT(NVARCHAR(12), columnA) = @searchColumnA
위와 같은 왼쪽 조건절 convert 쿼리로 변환되어 속도가 급속도로 저하된다.

선행 규칙은 다음과 같다.
  1. 사용자 정의 데이터 형식(가장 높음)
  2. sql_variant
  3. xml
  4. datetime
  5. smalldatetime
  6. float
  7. real
  8. decimal
  9. money
  10. smallmoney
  11. bigint
  12. int
  13. smallint
  14. tinyint
  15. bit
  16. ntext
  17. text
  18. image
  19. timestamp
  20. uniqueidentifier
  21. nvarchar(nvarchar(max) 포함)
  22. nchar
  23. varchar(varchar(max) 포함)
  24. char
  25. varbinary(varbinary(max) 포함)
  26. binary(가장 낮음)
반응형
반응형
쿼리 구문 작성

필요한 column만 명시한다.

SELECT * 을 사용하는 것은 피한다.
사용하지 않는 데이터를 호출하는 것만으로도 이미 많은 부하가 생긴다.
특히 text 타입의 데이터를 호출하는 경우는 그 정도가 심해진다.
data type의 byte가 적은 컬럼을 주로 사용하는 것이 좋다.

COUNT(*)을 사용하라.

COUNT(특정column) 으로 호출하는 경우가 있다.
이 경우 해당 컬럼의 NULL값을 제외한 COUNT를 가져오게 된다.
NULL값을 일일이 체크하면 호출 속도가 저하되게 된다.
NULL을 체크해야 하는 경우가 아닌 대부분의 경우 COUNT(*)을 체크한다.
COUNT(*)는 NULL값의 경우도 모두 count에 추가하지만 그로 인해 성능의 저하가 많이 줄어든다.

List 호출이 아닌 1 row 호출을 하는 경우 TOP 1을 사용한다.

성능상의 이슈로 이에 대해 권고하는 것은 아니다.
WHERE 조건절이 동적으로 변하는 경우를 고려한 작성을 하라는 것이다.
물론 QUERY를 호출하기 전 단계(비즈니스 로직 단계)에서 Validation 체크를 충분히 고려하겠지만 개발의 빈틈은 호출하는 쪽과 db쪽 양쪽 모두 없어야 한다.

where조건문의 왼쪽은 되도록 변형되지 않은 순수한 column만을 선언하라.

where name + '' = '조건' 과 같이 왼쪽 조건을 변형하지 말라.
where name = '' + '조건' 과 같이 오른쪽에 조건선언을 하라.
조건 일치를 매 로우마다 확인할 때 왼쪽 조건을 변형하게 된다.
그만큼 부하가 눈에 띄게 증가한다.

커서 및 임시테이블의 내용을 최대한 자제하라.

커서보다는 임시 테이블이 , 임시테이블 보다는 테이블 변수를 사용하는 것이 성능에 좋다.
커서의 경우 내부적으로는 임시 테이블을 사용하지만 임시 테이블을 쓴다고 부하가 더 발생하는 것이 아니다.
오히려 커서의 부가적 기능 때문에 서버 자원을 더 낭비하게 된다.
커서로 처리할 수 있는 것은 모두 임시 테이블이나 테이블 변수로도 처리가 가능하므로 되도록 커서를 쓰지 않는다.

JOIN을 사용하는 경우 INNER JOIN을 되도록 사용하라.

동일한 효과를 가지는 쿼리를 작성할 경우 INNER JOIN이 아닌 LEFT OUTER JOIN을 쓰는 경우가 있다. (습관적으로?)
확연히 속도가 차이가 나므로 INNER JOIN을 사용하는 것이 좋다.

하위쿼리의 사용시 불필요한 SELECT 구문은 줄여라.

아래와 같은 경우를 보자.
1.SELECT  kind     , SELECT name FROM kind_descriptoin WITH (READUNCOMMITTED) WHERE kind_id = kind    ...FROM list WITH (READUNCOMMITTED)WHERE kind = 1
kind라는 값은 WHERE 조건을 통해 하나의 값을 호출하게 되어있다.
kind가 1에 대한 kind_name의 값을 호출 하기 위해 서브쿼리를 사용하였지만 이는 올바른 사용이 아니다
SELECT가 해당 줄을 호출 할 때마다 서브쿼리에 있는 name을 구하는 쿼리를 호출하기 때문이다.
출력하는 줄이 많으면 많을 수록 서브쿼리의 실행 횟수또한 증가하게 되며 불필요한 부하를 가져온다.
따라서 위의 쿼리는 아래와 같이 사용하여야 옳다.
1.SELECT A.kind , B.name ...FROM list AS A WITH (READUNCOMMITTED)INNER JOIN kind_descriptoin AS B WITH (READUNCOMMITTED) ON A.kind = B.kind_idWHERE kind = 1

view의 총 사용을 줄여라.

view를 사용할 바엔 바로 사용하는 것이 단계 수를 줄이므로 더 낫다.

저장 프로시저를 사용하라.

저장 프로시저는 복잡한 SQL문을 단순화 시켜주고, 보안문제를 해결해주며 더 나아가 빠른 성능의 매개변수, 출력 매개변수, 리턴 값을 사용할 수 있다.

쿼리 구문 튜닝

MSSQL을 사용하는 경우 예상 실행 계획을 자주 확인하라.

MSSQL은 쿼리분석기에서 쿼리를 테스트 하기 편하다.
좋은 기능 중 하나가 예상 실행 계획인데 해당 쿼리가 성능상 어떤 장, 단점을 가지고 있는지 보기 쉽게 아이콘으로 표시해준다. (그래픽 실행 계획 아이콘)
실행계획의 내용은 버릴것이없으므로 꼼꼼히 따져봐야 한다.
튜닝의 시작은 성능 분석이다.

Index를 타는지 항상 체크하라.

Index를 활용하지 않은 검색은 데이터가 많으면 많을수록 성능은 급격히 떨어진다.
게시판 schema를 잘못 짠 경우 이런 현상이 발생하는데 이에 대한 점검을 늘 해야한다.
흔히 오해하기 쉬운 것 중 하나가 WHERE 조건절은 필요한 column만 존재해야 한다는 의식이다.
WHERE 조건절에는 Clustered Index Seek를 타기 위한 column이 우선 존재해야 하고 그 후에 원하는 데이터를 얻기 위한 조건절이 존재해야 한다.
조건자체가 Clustered Index column이면 제일 좋다.
조건절에 Index에 해당하는 columns이 존재하는 경우 우선적으로 해당 조건을 만족하는 행을 호출한 후 나머지 조건에 대해 만족하는 행을 다시 호출하게 된다.

Clustered Index Seek를 항상 체크하라.

Clustered Index Scan을 타는 것 만으로도 속도는 향상이 되지만 완전하진 않다.
Clustered Index column의 일정 구간을 타는 Seek여야 대량으로 증가하는 Data에 대한 부하를 감당할 수 있다.
이를 위해 Index의 구간 체크를 해야 한다.

만약 검색하는 column이 Clustered Index Column인 경우는 단방향 WHERE 조건문으로도 Index Scan이 성립이 된다.
자신의 컬럼에서 그대로 찾아서 시작 지점부터 끝까지 Index를 타면 되기 때문이다.

하지만 일반 Non Clustered Index의 경우는 Clustered를 찾기 위해 해당 column의 Clustered Index 정보를 호출해야 하는 부담이 생긴다.
왜냐하면 결국 호출을 하기 위해서는 해당 데이터의 위치를 찾아야 하고 이 위치를 가장 밀도있게 알고 있는 Clustered Index에서 해당 데이터의 위치를 찾아 가져오기 때문이다. (바로 찾게 되면 Clustered Index보다 범위가 크기 때문에 중간에 Clustered Index를 통해 찾는다.)
결국 구간 체크가 아닌 Non Clustered Index의 단방향 WHERE 조건문은 Clustered 의 전체 스캔을 하게 되는 결과를 가져온다.

Clustered Index와 Non Clustered Index의 Index 구조의 차이는 다음 두 페이지에서 확인할 수 있다.

 

기타 잡설

Index 설정시 DESC 정렬을 해야 빠르다?

그렇지 않다.
오름차순이건 내림차순이건 Index가 걸려있으면 조건에 따라 Clustered Index를 찾아 가게 된다.
다만 여러번 테스트를 해보았을 때 극소한 차이로 DESC가 걸린 정렬이 좀더 빠른 경우가 있었다.
이는 논리적인 검색으로 인한 빠르기 차이가 아닌 Data의 실제 물리적인 위치를 Index하는 과정에서 DESC가 좀더 효율적이기 때문이 아닐까 싶다. (이는 추측일 뿐이며 논리적으로 속도의 차이는 없다고 봐야 한다.)

Clustered Index Seek를 타면 무조건 빠르다?

그렇지 않다.
검색 조건이 모두 Index를 만족하지 않는 경우 WHERE 조건절에 Clustered Index column의 조건을 추가한 다음의 경우를 보자.
1.SELECT  * FROM test_query WITH (READUNCOMMITTED) WHERE idx > 0 AND content = 'testValue300000'

Clustered Index column이 검색 조건에 존재하므로 Clusterd Index Seek를 타게 된다.
하지만 성능상의 이슈는 없다.
왜냐하면 Clustered 전체 절을 검색하는 결과가 되기 때문이다.

Non Clustered Index column은 무조건 마지막엔 Clustered Index Column을 조회한다?

그렇지 않다.
Primary Key가 없는 (Clustered Index 설정이 없는) 테이블의 경우 결국 Non Clustered Index의 주소값을 이용해 데이터를 검색하게 된다.
다만 데이터 검색이 데이터의 순서와 index의 순서가 일치하는 Clustered Index가 더 빠르기 때문에 Clustered Index가 있는 경우 해당 Column의 주소값을 참조하는 것이다.

Clustered Index 검색이 무조건 Non Clustered Index보다 빠르다?
그렇지 않다.
단일 열 검색의 경우 두 검색의 속도는 거의 동일하다고 보아야 한다.
다만 검색한 내용이 범위대상과 같은 여러줄의 리스트가 되면 페이지의 단편화 현상과 연관하여 Non Clustered Index의 속도가 느려지게 된다.
이유는 여러열을 찾게 되는 경우. 이중 범위 검색의 경우 데이터가 서로 밀집되어 있으므로 Clustered Index에서는 바로 시작 지점에서 끝 지점까지의 데이터를 호출하면 되지만 Non Clustered Index는 각 열에 대해 포인트 점프를 통해 리스트를 호출해야 한다. 단편화가 되지 않은 경우 이 부분의 부하가 그리 크지 않지면 단편화가 심할 수록 그 속도는 저하되게 된다.
반응형
반응형
데이터 파일
  • 주 데이터 파일[.mdf]과 보조데이터 파일[.ndf]로 구분
  • 기본[디스크가 꽉 찰 때까지 10%씩 자동 증가]
로그 파일
  • 가상 로그파일 [.ldf]
  • 최소 단위 256kb로 구성
  • 기본[최대 2TB (2008 기준) 10%씩 자동 증가]

데이터베이스의 논리적 및 물리적 파일 이름



page

page에 들어가는 항목 8가지 : [msdn 링크]
페이지 유형 내용
데이터 text in row가 ON으로 설정된 경우에 text, ntext, image, nvarchar(max), varchar(max), varbinary(max)xml 데이터를 제외한 모든 데이터가 있는 데이터 행
인덱스 인덱스 항목
텍스트/이미지 큰 개체 데이터 형식:
  • text, ntext, image, nvarchar(max), varchar(max), varbinary(max)xml 데이터
데이터 행이 8KB를 초과하는 경우 가변 길이 열:
  • varchar, nvarchar, varbinarysql_variant
해당 페이지에 대해서 LOB (Large Object)로 지칭
전역 할당 맵(GAM) & 공유 전역 할당 맵(SGAM) 익스텐트가 할당되었는지 여부에 대한 정보 각 맵별로 64,000개의 익스텐트 또는 거의 4GB의 데이터를 처리
페이지의 사용 가능한 공간 페이지 할당 및 페이지의 사용 가능한 공간에 대한 정보
인덱스 할당 맵(IAM) 테이블 또는 인덱스에서 할당 단위당 사용하는 익스텐트에 대한 정보
대량 변경 맵(BCM) 마지막 BACKUP LOG 문 이후에 할당 단위당 대량 작업에 의해 수정된 익스텐트에 대한 정보
차등 변경 맵(DCM) 마지막 BACKUP DATABASE 문 이후에 할당 단위당 변경된 익스텐트에 대한 정보

IAM : Index Allocation Map
BCM : Bulked Change Map
DCM : Differential Change Map

extent

연속된 8개의 page로 구성[8 x 8 = 64KB] MB 당 16개의 extent로 구성되어 있음
  • 균일 extent -> 1개의 객체(table)이 해당 extent를 사용
  • 혼합 extent -> 여러개의 객체(table)이 해당 extent를 사용
  • 기본적으로 테이블을 처음 생성시 혼합 extent
혼합 및 단일 익스텐트


PFS (Page Free Space)

데이터 파일의 앞부분에 존재하는 특수 page.

개별 페이지의 할당 여부 및 각 페이지에 있는 빈 공간의 양과 같은 페이지의 할당 상태를 기록
각 페이지에 1바이트를 사용하여 페이지의 할당 여부를 기록
페이지가 할당된 경우 페이지의 상태를 [비어 있음], [1~50% 채워짐], [51~80% 채워짐], [81~95% 채워짐] 또는 [96~100% 채워짐]으로 기록
빈공간 추적에 사용


전역 할당 맵(GAM), 공유전역 할당 맵(SGAM)

익스텐트 할당 및 공간 관리 : [msdn 링크]


인덱스 할당 맵(IAM)

인덱스 및 테이블에 대해 extent 단위로 인덱스를 관리 : [msdn 링크]
새 행을 삽입해야 하는데 현재 페이지에 사용 가능한 공간이 없으면 IAM 및 PFS 페이지를 사용하여 할당할 페이지를 확인
힙 또는 텍스트/이미지 페이지의 경우 행을 보관하기에 충분한 공간이 있는 페이지를 확인

익스텐트를 관리하는 IAM(Index Allocation Map) 페이지


데이터 파일의 첫부분

위에서 나열된 요소들이 데이터 파일에 존재하는 순서는 다음과 같다.

익스텐트 할당 및 관리에 사용되는 페이지 차등 변경 맵 및 대량 변경 맵 페이지

두 데이터 파일의 순차적 페이지 번호
1.DBCC TRACEON(3604) -- 추적 플래그 : 3604[메세지를 화면에 출력], 3605[메세지를 로그에 출력]
2.DBCC PAGE(AION, 1, 1, 3)
3.DBCC TRACEOFF


실제 데이터 내용보기


비공식적인(문서화되지 않은) DBCC PAGE 명령어를 이용하면 실제 데이터 페이지 내용을 확인할 수 있다.

 행 오프셋이 있는 SQL Server 데이터 페이지


데이터 파일의 가장 작은 단위. page[8KB]

1 page : 8KB(8*1024 = 8192 byte)

헤더 - 96byte
데이터 영역의 크기 : 8192byte - 헤더(96byte) - 한 행당 2byte를 차지하는 오프셋 - 각 행에 들어가는 4byte = 최대 한 행의 영역 8060byte


PAGE 명령어의 사용

1.DBCC PAGE (DB 이름, 파일 번호, 페이지 번호, 옵션)
옵션 : 0[헤더만], 1[행 단위로], 2[페이지 그대로], 3[행 그리고 컬럼 값]

데이터의 내용을 보기 위해서는 page의 주소를 알아야 함 -> SQL SERVER에서 제공하는 시스템 뷰를 사용

sysindexes 뷰의 indid(index ID) 속성
  • 0 : 힙상의 데이터
  • 1 : 클러스터된 인덱스
  • 2~250 : 클러스터되지 않은 인덱스 또는 통계
  • 255 : text, ntext 형 데이터
01.--1. 해당 테이블의 첫번째 데이터가 있는 root 페이지의 주소값은 아래 시스템 뷰의 root 컬럼 확인
02.SELECT * FROM SYSINDEXES WITH (READUNCOMMITTED) WHERE ID = OBJECT_ID('테이블이름') -- first 또는 root 컬럼의 첫 4byte(8자리)를 확인하여 byte swapping (대략 0XB6FD00000100 형태->0000FDB6)
03. 
04.--2. 위에서 확인한 root 컬럼의 첫 4자리 16진수 값을 10진수로 변환
05.SELECT CONVERT(INT, 0xB4) -- 이경우 180
06. 
07.--3.해당 값의 페이지를 추적하여 페이지를 확인
08.DBCC TRACEON(3604) -- 추적 플래그 : 3604[메세지를 화면에 출력], 3605[메세지를 로그에 출력]
09.DBCC PAGE(AION, 1, 180, 3)
10.DBCC TRACEOFF

 

행 구조

구성 요소

  • 헤더 : 4byte
    • 상태 비트 : 2byte
    • 고정 컬럼 길이 : 2byte : 헤더(4byte)를 포함한 바이트 수를 지정
  • 고정 컬럼 데이터 : [m]byte
  • 전체 컬럼 수 : 2byte
  • NULL 비트맵 : 컬럼 당 1bit
    • 테이블의 5번째 컬럼 값이 null이면 10 (0x10 -> 00010000)으로 5번째 컬럼의 null 값 여부를 체크
  • 가변 컬럼 수 : 2byte
  • 컬럼 오프셋 : 2byte x 가변 컬럼 수
  • 가변 컬럼 데이터 : n byte
문자열의 경우 숫자값의 경우 그대로 해석
기록 단위 : 16bit = 256 = 2^8 = 1byte 2자리
 
2005의 경우는 기존과 다르게 3번 옵션이 2번 옵션과 동일하게 byte swap 상태로 출력 (2, 3 옵션 출력 통일), 실제 내부 저장은 동일
고정컬럼 데이터가 우선 저장된 이후 가변컬럼 데이터가 저장
가변 컬럼의 경우 저장된 위치를 파악하기 위한 오프셋을 가짐
  • 장점 : 공간 절감 효과가 큼, null값인 경우 아예 공간을 차지하지 않음
  • 단점 : 변동적인 오프셋을 이용하여 실제 컬럼의 위치를 찾아가야 하므로 CPU 부하가 증가됨
2자리 8bit -> 1byte
 
text, ntext, image 형 컬럼의 경우 데이터 행에는 루트를 가리키는 16byte의 포인터만 저장, 루트에서 B-트리 구조로 데이터를 분산 저장

행 구조 데이터 확인을 위한 간단한 명령어
1.SELECT CONVERT(데이터타입, 저장된 데이터)
2.-- 또는 역검색
3.SELECT CONVERT(BINARY, 호출되길 원하는 데이터)

 

tip

할당된 page에 대한 정보 조회 sp
sp_로 시작되는 프로시져 (master db에 존재하는 sp로 해당 db 서버의 모든 catalog에서 사용 가능한 system procedure)

1.EXEC sp_spaceused [테이블명]
기타 물리적 데이터들에 대한 내용 확인은 SQL SERVER에서 제공하는 시스템 뷰를 통해 확인 가능 [msdn 링크 - 호환성 뷰 참조]
DBCC TRACEON 명령어의 추적플래그 정의 - [msdn 링크]
반응형

'연구개발 > DBA' 카테고리의 다른 글

varchar 타입 컬럼 검색 SP 작성 시 주의사항  (0) 2011.09.22
성능 향상을 위한 query 작성과 tuning  (0) 2011.09.22
전체 텍스트 검색 full text search  (0) 2011.09.22
인덱스 페이지 구조  (0) 2011.09.21
SYSINDEXES  (0) 2011.09.08

+ Recent posts

반응형