728x90

SQL Server for Developer: 관리자를 위한 튜닝 가이드

SQL인스턴스 환경 설정

차주언 | SQL 컨설턴트

SQL인스턴스 환경 설정

다른 SQL인스턴스 설정값들은 상황에 따라 특수하게 공부를 해야하겠지만 아래의 3가지에 비에 그 중요도가 무척이나 떨 어집니다 왜냐하면 SQL이 거의 자동으로 최적값에 세팅되어 있기 때문입니다.

번호 수칙 체크
1 서비스 이상 발생시 자동 시작을 설정해두었는가?  
2 고정 메모리를 사용하도록 해두었는가?  
3 SET OPTION을 사용하는가?  

수칙1. 서비스 이상 발생시 자동시작을 설정해두었는가?

첫번째는 시스템 가동시 항상 서비스는 시작되어야 한다는 것이고 두번째는 문제가 생겨서 갑자기 작동을 멈추면 알아서 다시 시작되어야 한다는 것입니다.

[따라하기]
SQL Server및 Agent 서비스 자동시작 모드로 설정하기
1.자동시작 설정을 해보겠습니다.[서비스 관리자]를 선택한 후 다음의 [자동 시작]항목을 확인합니다.





2.그 다음은 문제 발생시 자동시작 설정입니다. SQL서버 엔터프라이즈 관리자에서 SQL Server 에이전트 서비스에서 [등록정보]를 선택한 후 [고급]텝을 선택한 후 다음을 체크합니다.

[01-03 자동으로 다시 시작]


3.위와 같이 적용해둔 후 SQL서버 서비스 및 에이전트 서비스를 재시작 합니다.

수칙2. 고정 메모리를 사용하도록 해두었는가?

SQL 서버는 필요할 때 메모리를 필요한 만큼 가져갔다가 다른 응용프로그램이 가져가게 할 수 도 있으며, 또한 SQL 서버 전용으로 메모리를 아예 고정하는 방법도 있습니다. 상식적으로 생각해보아도 전용으로 사용하는 것이 SQL 서버를 위해 효과적인 것을 알 수 있습니다.

[따라하기]
SQL 서버는 오직 데이터베이스 서비스만을 위해 사용하는 것이 좋다. 운영체제가 사용할 약간량만을 제외한 나머지를 SQL 서버 서비스만을 위해 강제 할당 하는 것이 가장 효율적입니다.

1.엔터프라이즈 관리자를 실행하여 메모리를 설정하고자 하는 서버를 선택합니다.

[02-01 엔터프라이즈 관리자 실행]


2.서버 노드를 선택한후 등록 정보를 실행합니다. 실행후 메모리텝을 선택합니다. 기본으로 [SQL Server 메모리를 동적으로 구성]에 체크되어있습니다.

[02-02 메모리텝(기본은 동적으로 구성)]


3.운영체제를 위한 적당량(200메가) 를 남겨두고 나머지는 SQL 서버를 위해 할당합니다. [고정된 메모리] 체크박스를 선택하고 [SQL 서버용으로 실제 메모리 예약]도 선택합니다. 이렇게 세팅해야만 다른 응용프로그램이 SQL 서비스에게서 메모리를 빼앗아가지 못합니다.

[02-03 고정된 메모리 크기 사용 및 실제메모리 예약]


4.설정이 끝나면 역시 서비스를 재시작해야합니다.

[02-04 서비스 재시작]


수칙 3. SET OPTION을 사용하는가?

가. SET NOCOUNT ON
나. SET ANSI_NULLS ON
다. SET QUOTED_IDENTIFIER ON
라. SET LOCKTIMEOUT 값 지정(디폴트 -1 : 무한대)

SET NOCOUNT ON 이란? 메시지 창에 ~행이 적용되었습니다 하고 나타나는 시스템 메시지 입니다. 쿼리수가 많아지면 이런 메시지는 네트워크상에 쓰레기가 되니 아예 발생하지 않도록 하는 것이 시스템에 유리합니다.
SET ANSI_NULLS ON이란? SQL-92 표준에서는 NULL 값에 대한 Equals(=) 또는 Not Equal(<>) 비교의 결과가 검색되지 않아야 합니다. 쿼리분석기에서 도움말 SET ANSI_NULLS ON를 검색한 후 예제를 따라해보십시오.
SET QUOTED_IDENTIFIER ON을 설정하면 SET QUOTED_IDENTIFIER 옵션을 ON으로 설정하면 식별자를 큰따옴표로 구분할 수 있으며, 리터럴은 작은따옴표로 구분해야 합니다.
SET LOCKTIMEOUT으로 잠금이 해제될 때가지 명령문이 기다려야 할 시간을 밀리초 단위로 지정할 수 있습니다. -1은 초기상태 무한대기 입니다.
다음의 따라하기를 참조로 위의 4가지 설정을 서버차원에서 하도록 합니다.

[따라하기 - SET NOCUNT ON의 의미실험]
1.쿼리분석기에서 다음의 쿼리를 실행합니다.

USE pubs
GO

SELECT * FROM titles

2.결과창에서 메시지 탭을 선택합니다.



3.메시지 탭에 (18개 행 적용됨) 이 보입니다. 이런 메세지도 수가 많아지면 부하가 발생합니다.

4.쿼리에서 SET NOCOUNT ON 실행 후 다시해봅니다.(일반적으로 모든 저장 프로시저의 첫번째 문장은 SET NOCOUNT ON 문이 되어야 합니다.)



5.훌륭하게 적용되었으나, SET문은 단지 지금 세션에만 적용되는 것 입니다. 서버차원에서 다시 설정할 필요가 있습니다.



6.훌륭하게 적용 되었습니다. 다른 것도 실험해 봅시다.

제공 : DB포탈사이트 DBguide.net

출처명 : 한국마이크로소프트(주)
728x90

SQL Server for Developer: 관리자를 위한 튜닝 가이드

데이터베이스 설정

차주언 | SQL 컨설턴트

데이터베이스 설정

번호 수칙 체크
1 데이터베이스 기본 크기 및 증가율을 넉넉히 잡아 두었는가?  
2 필요할 경우 읽기 전용을 사용하는가? (온라인 분석서버)  

수칙1. 데이터베이스 기본 크기 및 증가율을 넉넉히 잡아 두었는가?

데이터베이스 등록정보를 보고 기본크기를 여유있게 잡으며 증가단위는 메가단위로 1달에 1번이상 데이터베이스 자동증가가 이뤄지지 않도록 작성하는 것이 좋습니다. 가장 중요한 것은 최대 크기를 설정해두는 것입니다.

[따라하기 데이터베이스 속성 설정]
1.다음의 붉은 동그라미 부분을 설정하면 됩니다.



2.로그부분도 위의 3 부분을 수정해 줍니다.

수칙2. 필요할 경우 읽기 전용을 사용하는가? (온라인 분석서버)

OLTP 즉 다수의 사용자가 데이터를 읽는 경우는 적절한 잠금 장치로 데이터의 일관성을 유지할 필요가 있으나 OLAP 분석 서버인 경우는 그럴필요가 없으므로 읽기 전용 속성이 유리합니다.

[따라하기 속성]
1.데이터베이스를 선택한 후 등록정보를 선택합니다. 옵션을 선택합니다.



[팁 데이터베이스 작성 스크립트 뽑아내기]
1.엔터프라이즈 관리자를 실행합니다. 데이터베이스 항목을 선택한 후 모든작업 > SQL스크립트 생성 을 선택합니다.

2.옵션에서 데이터베이스 스크립팅을 선택한 후 확인을 클릭합니다.



3.다음은 저장된 파일을 열기만 하면됩니다.

제공 : DB포탈사이트 DBguide.net

출처명 : 한국마이크로소프트(주)
728x90

SQL Server for Developer: 관리자를 위한 튜닝 가이드

인덱스

차주언 | SQL 컨설턴트

인덱스

번호 수칙 체크
1 적절한 인덱스가 걸려있는가? (I/O 가 많은 경우 실행 계획 재검사)  
2 인덱스 튜닝마법사로 점검했는가?  
3 상황 발생시 인덱스 채우기 비율을 조정하는가?  

수칙1.적절한 인덱스가 걸려 있는가?

적절한 인덱스가 걸려있는지 인덱스 튜닝마법사로 확인할 수 있습니다. 또는 CTRL + K로 실행계획을 관찰 해도 됩니다.

인덱스를 만들어야 하는 장소
가. 참조키
나. 참조키가 아니더라도 join에 빈번히 사용되는 경우
다. select절에 자주 사용되는 칼럼
라. where,group by,order by절에 자주 사용되는 곳

수칙2.인덱스 튜닝마법사로 점검했는가?

인덱스란 책의 목차나 책 뒤쪽의 찾아보기와 매우 유사합니다. 예를 들면 40 메가의 데이터중 필요한 내용을 찾고자 한다면 40 메가를 모두 검색해야하지만 인덱스를 만들어 둔다면 인덱스만 읽음으로써 보다 적은 리소스에 사용만으로, 필요한 내용 검색을 끝낼 수 있습니다.

[따라하기 적절한 인덱스 자동 만들기]
1.다음과 같은 테이블을 예제 테이블을 pubs 데이터베이스에 만들어서 가상 Data 10 만개를 입력해 봅시다.



2.10 만개의 데이터가 입력됐으면 select 쿼리로 실험을 시작하도록 합니다. 먼저 총 I/O 가 얼마가 일어나는지 또 실행 계획은 무엇인지 알아보겠습니다. 단축키 CTRL + K 를 클릭하고 다음의 설정을 한후 쿼리를 실행합니다.



3. 데이터 한 개를 가져오기위해 테이블 전체를 검색하고 Data 페이지 6250 페이지를 읽었군요. 6250 페이지는 6250 * 8 다시말해 약 50 메가를 검색하고 있습니다.

4. 여기에서 인덱스를 만들어 보겠습니다.

create index idx on tb_test(id)

5.다시 쿼리를 실행하면 I/O 는 몇페이지가 나옵니까?

select * from tb_test where id = 1

6.인덱스를 제거하고 이번에는 자동 인덱스 추천을 한번 해보겠습니다.

drop index tb_test.idx

7.select 쿼리를 드래그 하여 선택 후 쿼리 메뉴에서 인덱스튜닝마법사(CTRL+I)를 선택합니다.





08.SQL쿼리분석기 선택 체크를 선택합니다.



09. 튜닝할 테이블만을 선택합니다.



10. 다음과 같은 인덱스가 권장 되었습니다.



11. 다음과 같이 변경 내용 적용과 함께 인덱스를 만드는데 사용한 소스도 저장합니다.



12. 마침을 클릭합니다. 인덱스도 훌륭히 적용된 것을 알 수 있습니다. 생성된 쿼리도 열어서 확인합니다.





13. 인덱스 결과도 확인합니다. 응용으로는 한번에 많은 쿼리를 선택한 후 인덱스 튜닝 마법사를 실행 할 수 있다는 것입니다.

sp_helpindex tb_test

[관련링크]
http://support.microsoft.com/default.aspx?scid=kb;ko;271509

위의 파일에 오류가 있는데 수정한 것은 다음과 같습니다.

use master
go

if exists (select * from sysobjects where id = object_id('dbo.sp_blocker_pss80') and
sysstat & 0xf = 4)
drop procedure dbo.sp_blocker_pss80
GO

create proc sp_blocker_pss80 (@fast int = 0)
as
set nocount on
declare @spid varchar(6), @uid varchar(6), @blocked varchar(6)
declare @tmpchar varchar(255)
declare @time datetime

select @time = getdate()

declare @probclients table(spid smallint, blocked smallint, waittype binary(2),
primary key (blocked,spid))
insert @probclients select spid, blocked, waittype from sysprocesses where blocked!=0
or waittype != 0x0000
if exists (select spid from @probclients)
begin
select @tmpchar='Start time: ' + convert(varchar(26), @time, 113)
print @tmpchar

insert @probclients select blocked, 0, 0x0000 from @probclients
where blocked not in (select spid from @probclients) and blocked != 0

print ' '
if (@fast = 1)
begin
select spid, status, blocked, open_tran, waitresource, waittype,
waittime, cmd, lastwaittype, cpu, physical_io,
memusage,last_batch=convert(varchar(26), last_batch,113),
login_time=convert(varchar(26), login_time,113), net_address,
net_library,dbid, ecid, kpid, hostname,hostprocess,
loginame,program_name, nt_domain, nt_username, uid, sid
from master..sysprocesses
where blocked!=0 or waittype != 0x0000
or spid in (select blocked from @probclients where blocked != 0)
or spid in (select spid from @probclients where blocked != 0)

select spid = convert (smallint, req_spid),
ecid = convert (smallint, req_ecid),
rsc_dbid As dbid,
rsc_objid As ObjId,
rsc_indid As IndId,
Type = case rsc_type when 1 then 'NUL'
when 2 then 'DB'
when 3 then 'FIL'
when 4 then 'IDX'
when 5 then 'TAB'
when 6 then 'PAG'
when 7 then 'KEY'
when 8 then 'EXT'
when 9 then 'RID'
when 10 then 'APP' end,
Resource = substring (rsc_text, 1, 16),
Mode = case req_mode + 1 when 1 then NULL
when 2 then 'Sch-S'
when 3 then 'Sch-M'
when 4 then 'S'
when 5 then 'U'
when 6 then 'X'
when 7 then 'IS'
when 8 then 'IU'
when 9 then 'IX'
when 10 then 'SIU'
when 11 then 'SIX'
when 12 then 'UIX'
when 13 then 'BU'
when 14 then 'RangeS-S'
when 15 then 'RangeS-U'
when 16 then 'RangeIn-Null'
when 17 then 'RangeIn-S'
when 18 then 'RangeIn-U'
when 19 then 'RangeIn-X'
when 20 then 'RangeX-S'
when 21 then 'RangeX-U'
when 22 then 'RangeX-X'end,
Status = case req_status when 1 then 'GRANT'
when 2 then 'CNVT'
when 3 then 'WAIT' end
,req_transactionID As TransID,
req_transactionUOW As TransUOW
from master.dbo.syslockinfo s,
@probclients p
where p.spid = s.req_spid

end -- fast set

else
begin -- Fast not set
select spid, status, blocked, open_tran, waitresource, waittype,
waittime, cmd, lastwaittype, cpu, physical_io,
memusage,last_batch=convert(varchar(26), last_batch,113),
login_time=convert(varchar(26), login_time,113), net_address,
net_library,dbid, ecid, kpid, hostname,hostprocess,
loginame,program_name, nt_domain, nt_username, uid, sid
from master..sysprocesses

print ''
print 'SPIDs at the head of blocking chains'
select spid from @probclients
where blocked = 0 and spid in (select blocked from @probclients where spid !=
0)

print ''

select spid = convert (smallint, req_spid),
ecid = convert (smallint, req_ecid),
rsc_dbid As dbid,
rsc_objid As ObjId,
rsc_indid As IndId,
Type = case rsc_type when 1 then 'NUL'
when 2 then 'DB'
when 3 then 'FIL'
when 4 then 'IDX'
when 5 then 'TAB'
when 6 then 'PAG'
when 7 then 'KEY'
when 8 then 'EXT'
when 9 then 'RID'
when 10 then 'APP' end,
Resource = substring (rsc_text, 1, 16),
Mode = case req_mode + 1 when 1 then NULL
when 2 then 'Sch-S'
when 3 then 'Sch-M'
when 4 then 'S'
when 5 then 'U'
when 6 then 'X'
when 7 then 'IS'
when 8 then 'IU'
when 9 then 'IX'
when 10 then 'SIU'
when 11 then 'SIX'
when 12 then 'UIX'
when 13 then 'BU'
when 14 then 'RangeS-S'
when 15 then 'RangeS-U'
when 16 then 'RangeIn-Null'
when 17 then 'RangeIn-S'
when 18 then 'RangeIn-U'
when 19 then 'RangeIn-X'
when 20 then 'RangeX-S'
when 21 then 'RangeX-U'
when 22 then 'RangeX-X'end,
Status = case req_status when 1 then 'GRANT'
when 2 then 'CNVT'
when 3 then 'WAIT' end
,req_transactionID As TransID,
req_transactionUOW As TransUOW
from master.dbo.syslockinfo
end -- Fast not set

dbcc traceon(3604)
Print ''
Print ''
Print '*********************************************************************'
Print 'Print out DBCC Input buffer for all blocked or blocking spids.'
Print 'Print out DBCC PSS info only for SPIDs at the head of blocking chains'
Print '*********************************************************************'

declare ibuffer cursor fast_forward for
select cast (spid as varchar(6)) as spid, cast (blocked as varchar(6)) as blocked
from @probclients
where (spid <> @@spid) and (blocked!=0 or waittype != 0x0000
or spid in (select blocked from @probclients where blocked != 0))
open ibuffer
fetch next from ibuffer into @spid, @blocked
while (@@fetch_status != -1)
begin
print ''
print ''
print 'DBCC INPUTBUFFER FOR SPID ' + @spid
exec ('dbcc inputbuffer (' + @spid + ')')
print ''
if (@blocked = '0')
-- if DBCC PSS is not required, comment the line above, remove the
-- comment on the line below and run the stored procedure in fast
-- mode
-- if (@blocked = '0' and @fast = 0)
begin
print 'DBCC PSS FOR SPID ' + @spid
exec ('dbcc pss (0, ' + @spid +')')
print ''
print ''
end
fetch next from ibuffer into @spid, @blocked
end
deallocate ibuffer

if datediff(millisecond, @time, getdate()) > 1000
begin
select @tmpchar='End time: ' + convert(varchar(26), getdate(), 113)
print @tmpchar
end

dbcc traceoff(3604)
end -- All
go

[참고] 그러나 현업에선 프로 파일러가 UI부하 때문에 사용이 망설여 집니다. 그래서 proc 로 제작해서 사용하는 것을 권장합니다. 위의 시스템 프로시저를 제작한 후 사용해 봅니다. 직접 아래 쿼리를 수행하거나 결과를 파일로 만들어 저장할 수 있습니다.

-- checkblk.sql

DBCC TRACEON (3604)
GO
WHILE 1=1
BEGIN
-- EXEC sp_blocker_pss80
-- Or for fast mode
EXEC sp_blocker_pss80 1
WAITFOR DELAY '00:00:15'
END
GO

실제 위의 파일을 저장한 곳에서 다음의 명령 프롬프트에서 이렇게 수행하면 됩니다.

osql -E -icheckblk.sql -ocheckblk.out -w2000

그 다음은 결과만 분석하면 됩니다. 락에 대기중인 쿼리가 딱 나와있습니다.

수칙3.상황 발생시 인덱스 채우기 비율을 조정하는가?

인덱스는 검색할 때 속도는 무척 우수합니다. 그러나 insert작업시 인덱스의 많은 변화가 요구되는 페이지 분할(Page Split) 발생할 수가 있어서 아예 여유공간을 비워두는 것이 좋습니다.

[따라하기]
01. 데이터베이스 유지관리 마법사 노드에서 마우스 오른쪽 클릭 후 새 유지관리 계획 마법사를 실행합니다.



02.인덱스를 정돈할 데이터베이스를 선택합니다



03.다음과 같이 인덱스 비우기 비율을 적당량(상황에따라)을 선택한 후 다음버튼을 클릭합니다.





04. 정기적으로 재정비 해주면 좋습니다.

제공 : DB포탈사이트 DBguide.net

출처명 : 한국마이크로소프트(주)

+ Recent posts