반응형
반응형

/* 1.View는 원본의 select구문을 실행시키주는 역할로서
     서버 자체 속도 향상의 효과는 없다.
   2.View 실행시 원본 table에 접근하여 결과 값을 찾는 행동을
  index화 시켜 줌으로서 쿼리문의 속도향상을 꾀 할 수있다.
   3.하지만, 원본 table의 값이 바뀌면 indexing view도 값을 바꿔
  줘야 하기 때문에, 보통의 index가 가지고 있는 단점인 서버부하
  가 빈번히 일어나게 된다.
  그러므로, 값이 자주 바뀌는 동적인 table보다는 정적인 table에
  서 생성하는게 좋다.
*/

ex)
select * from sawon
select * from dept

 

sp_helpconstraint dept
sp_helpconstraint sawon

 

create view a_money with schemabinding
as
select count_big(*) '부서인원'
    ,d.deptno
    ,sum(isnull(s.sal,0)*12+isnull(s.comm,0)) 'yearpay'
from dbo.sawon s inner join dbo.dept d
on s.deptno = d.deptno
group by d.deptno

 

create unique clustered index a_u_clidx_a_money_deptno 
on a_money(deptno);


select * from a_money

반응형

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

INDEX 2  (0) 2010.06.18
INDEX  (0) 2010.06.18
UNION ,UNION ALL ,INTERSECT and EXCEPT  (0) 2010.06.18
join & subquery 연습  (0) 2010.06.18
그룹함수  (0) 2010.06.18
반응형

UNION ,UNION ALL ,INTERSECT and EXCEPT

ex)  CREATE TABLE M1
      (
       NUM INT IDENTITY(1,1) NOT NULL,
      NAME VARCHAR(1) NOT NULL
       );

SELECT * INTO M2 FROM M1;

 

SELECT * FROM M1;
 INSERT INTO M1(NAME) VALUES('A');
 INSERT INTO M1(NAME) VALUES('B');
 INSERT INTO M1(NAME) VALUES('C');
 INSERT INTO M1(NAME) VALUES('H');

 

SELECT * FROM M2;
 INSERT INTO M2(NAME) VALUES('D');
 INSERT INTO M2(NAME) VALUES('E');
 INSERT INTO M2(NAME) VALUES('F');
 INSERT INTO M2(NAME) VALUES('H');

 

SELECT * FROM M1                SELECT * FROM M1
union      -합집합                     union all  -- 합집합 and 교집합 
SELECT * FROM M2                SELECT * FROM M2

               

 

SELECT * FROM M1                         SELECT * FROM M1
 intersect           -- 교집합                 EXCEPT                 -- M1- 교집합
SELECT * FROM M2;                        SELECT * FROM M2;             
              


반응형

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

INDEX  (0) 2010.06.18
INDEXING VIEW  (0) 2010.06.18
join & subquery 연습  (0) 2010.06.18
그룹함수  (0) 2010.06.18
통계를 편리하게 확인  (0) 2010.06.17
반응형

update dept set dname='연구1부',loc='대전'where deptno=20;
update dept set dname='연구2부' where deptno=30;

 

/* 1. SAWON 테이블에서 일용이와 같은 부서에 있는 
  모든 사원의 이름과 입사일자를 출력하는 SELECT문을 
  작성하시오.*/

 

select s.name as '사원이름', s.hiredate as '입사일자', d.dname as '부서'
   from sawon s inner join dept d
   on s.deptno = d.deptno
   where d.deptno =(select deptno from sawon where name ='일용이')

 

select name, hiredate
 from sawon
 where deptno = (select deptno 
      from sawon
     where name = '일용이')
   and
   name != '일용이'

 

/* 2. SAWON 테이블에서 평균 급여 이상을 받는 모든 
  종업원에 대해서 종업원 번호와 이름을 출력하는 
  SELECT문을 작성하시오.
  단, 급여가 많은 순으로 출력하라. */     
 --총무부서 평균급여이상 받는 모든 사원을 적으시오

 

select sano '사원번호', name '사원이름', sal '급여'
from sawon
where sal >= (select avg(isnull(sal,0))
           from sawon)

 
select s.sano '사원번호', s.name '사원이름', s.sal '급여'
 from sawon s inner join dept d
 on s.deptno = d.deptno
 where sal >= (select avg(isnull(sal,0))
           from sawon)

 

 --총무부서 평균급여이상 받는 모든 사원을 적으시오

 

select sano,name,sal
from sawon
where sal >= (select avg(isnull(sal,0))
    from sawon s inner join dept d
    on s.deptno = d.deptno
    where d.dname='총무부')

 

select sano,name,sal
from sawon
where sal >=(select avg(isnull(sal,0))
    from sawon 
    where deptno =
    (select deptno
     from dept where dname = '총무부'))
  

  
select * from dept


/* 3. SAWON 테이블에서 이름에 '원' 이있는 사원이 
  근무하는 모든 종업원애 대해서 사원 번호, 이름, 
  급여를 출력하는 SELECT 문을 출력하시오. 
  단 사원번호순으로 출력하세요 */

select sano, name, sal
from sawon
where deptno in (select deptno
     from sawon
     where name like '%원%')

 

select sano, name, sal
from sawon
where deptno in (select distinct deptno    
     from sawon
     where name like '%원%')
 
 
/* 4. SAWON 테이블에서 부서 위치가 대전인 모든 종업원에 
  대해 이름, 직급, 급여를 출력하는 SELECT문을 
  작성하시오.  */
 
select name as '사원이름',jik as '직급',sal as '급여'
 from sawon s inner join dept d
 on s.deptno = d.deptno
 where d.loc ='대전'
 
      
/* 5. SAWON 테이블에서 한석규에게 보고하는 모든 사원의 
  이름과 급여를 출력하는 SELECT문을 작성하시오.*/


select [name] as '사원이름', sal as '급여'
 from sawon
 where mgr in (select s1.mgr
      from sawon s1 left outer join sawon s2
      on s1.mgr = s2.sano
      where s2.name like '한석규')

 

select [name] as '사원이름', sal as '급여'
 from sawon
 where mgr = (select sano from sawon where name='한석규')

 

select name,sal
from sawon a inner join (select sano from sawon where name='한석규') b
 on a.mgr=b.sano


/* 6. SAWON 테이블에서 총무부 사원의 이름 직급를 
  출력하는 SELECT문을 출력하시오*/


select name as '사원이름', jik '직급'
from sawon
where deptno = (select deptno
     from dept
     where dname='총무부');

 

select s.name as '사원이름', s.jik '직급'
 from sawon s join dept d
 on d.deptno = s.deptno
 where d.dname='총무부';

     

/* 7. 테이블에서 월급이 연구2부 최저 월급보다 
  높은 사원을 출력하는 SELECT문을 작성하시오. */


select name as '사원이름', sal '연봉'
from sawon
where sal > (select min(isnull(sal,0))
   from sawon s inner join dept d
   on s.deptno = d.deptno
   where d.dname ='연구2부');

 

              
/* 8. 사원테이블에서 부서10에서 부서30의 사원과 
  같은 업무를 맡고 있는 사원과 이름을 출력하시오*/

select name as '사원이름', jik as '직급'
 from sawon
 where deptno =10 and jik in (select distinct jik  -- in and
                        from sawon                    --  all 부등호 상관없이 and
         where deptno=30);               -- any 부등호 or
  
   
/* 9. 사원테이블에서 이미자와 직급도 월급도 
  같은 사원의 모든 정보를 출력하는 SELECT 문을 
  작성하시오 */                            

select *
from sawon
where sal = (select sal
    from sawon
    where name ='이미자')
   and jik = (select jik
     from sawon
     where name ='이미자')
   and name!='이미자'

 

select * 
from sawon s inner join (select sal,jik from sawon where name='이미자') a
on s.jik=a.jik
where a.sal=s.sal
   
/* 10. SAWON 테이블에서 직급이 고소영과 같거나 
  월급이 이미자이상인 사원의 정보를 이름,직급,
  부서번호,급여를 출력하는 SELECT 문을 작성하시오
  단,업무별,월급이 많은 순으로 출력*/

select name as '사원이름', jik as '직급', deptno as '부서번호', sal as '급여'
from sawon
where jik=(select jik
   from sawon
   where name = '고소영')
 or sal >= (select sal
    from sawon
    where name = '이미자')
order by 3,4 desc;
   


/* 11. SAWON 테이블에서 네석규 또는 박찬호와 월급이 
  같은 사원의 정보를 이름,직급,급여를 출력하는 
   SELECT 문을 작성하시오 */

 

select name as '사원이름', jik as '직급', sal as '급여'
from sawon
where name not in ('네석규','박찬호') and 
sal in (select sal from sawon where name in ('네석규','박찬호'))

 


/* 12. SAWON 테이블에서 서울에서 근무하는 사원과 
  같은 직급을 갖는 사원의 이름, 직급을 출력하는 
  SELECT문을 작성하시오 */

 

select s.name as '사원이름', s.jik as '직급'
from sawon s inner join dept d
on s.deptno = d.deptno
where jik in (select jik from dept where loc='서울')


/* 13. SAWON테이블에서 부서별로 월급이 부서별 평균보다 
  높은 사원을 부서번호, 이름,급여를 출력하는 
  SELECT문을 작성하시오 */

 

select deptno as '부서번호', name as '사원이름',sal as '급여'
from sawon
 where deptno=10 and sal > (select avg(isnull(sal,0)) from sawon where deptno=10)
  or   deptno=20 and sal > (select avg(isnull(sal,0)) from sawon where deptno=20)
     or   deptno=30 and sal > (select avg(isnull(sal,0)) from sawon where deptno=30) 
     or   deptno=40 and sal > (select avg(isnull(sal,0)) from sawon where deptno=40)

 

select deptno as '부서번호', name as '사원이름',sal as '급여'
from sawon s
where sal > (select avg(isnull(sal,0))
     from sawon 
    where deptno=s.deptno)

 

select a.deptno, a.name, a.sal
 from sawon a inner join
  (select deptno, avg(sal) as avg_sal
  from sawon
  group by deptno) b
 on a.deptno=b.deptno
 where a.sal > b.avg_sal
 
/* 14. 사원 테이블에서 직급별로 월급이 회사내 평균 
  월급보다 낮은 사원을 부서번호,이름,급여를 출력하는 
  SELECT 문을 작성하시오 */

 

select deptno as '부서번호', name as '사원이름',sal as '급여'
from sawon
 where sal < (select avg(isnull(sal,0)) from sawon)


select deptno as '부서번호', name as '사원이름',sal as '급여'
from sawon s
group by deptno, name, sal
having avg(isnull(sal,0)) < (select avg(isnull(sal,0))
     from sawon s
    where jik=s.jik
    )

 

select a.deptno as '부서번호', a.name as '사원이름',a.sal as '급여'
from sawon a inner join( select avg(isnull(sal,0)) avg_sal,jik
                  from sawon 
                  group by jik) b
on a.jik=b.jik
where a.sal < b.avg_sal


/* 15. 사원 테이블에서 적어도 한명 이상으로부터 보고를 
  받을 수 있는 사원을 업무, 이름, 사원번호, 
  부서번호를 출력하는 SELECT문을 작성하시오. */

select d.dname as '부서', s.name as '사원이름', s.sano as '사원번호', s.deptno as '부서번호'
from sawon s join dept d
on s.deptno = d.deptno
 where mgr not in(
            select max(mgr) from sawon
       where mgr is not null
       group by deptno )
  or mgr is null

 

select d.dname as '부서', s.name as '사원이름', s.sano as '사원번호', s.deptno as '부서번호'
  from sawon s join dept d
  on s.deptno = d.deptno
  where sano in(
   select sano from sawon
   intersect
   select mgr from sawon)

 

select d.dname as '부서', s.name as '사원이름', s.sano as '사원번호', s.deptno as '부서번호'
 from sawon s join dept d
  on s.deptno = d.deptno
 where sano in (select distinct mgr from sawon)

     
/* 16. SAWON 테이블에서 말단 사원의 사원번호, 이름, 
  업무, 부서번호를 출력하는 SELECT문을 작성하시오 */


select s.sano as '사원번호', s.name as '사원이름', d.dname as '업무' , d.deptno as '부서번호'
from sawon s inner join dept d
on s.deptno=d.deptno
 where s.mgr in (select max(mgr) from sawon
       where mgr is not null
       group by deptno )

 

select s.sano as '사원번호', s.name as '사원이름', d.dname as '업무' , d.deptno as '부서번호'
from sawon s inner join dept d
on s.deptno=d.deptno
 where s.sano not in (select distinct isnull(mgr,0) from sawon)

      

반응형

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

INDEXING VIEW  (0) 2010.06.18
UNION ,UNION ALL ,INTERSECT and EXCEPT  (0) 2010.06.18
그룹함수  (0) 2010.06.18
통계를 편리하게 확인  (0) 2010.06.17
ANSI_NULLS NULL값과 비교  (0) 2010.06.08
반응형
select 

     deptno as '부서번호',
     case when substring(jubun,7,1) in ('1','3') then '남'
     else '여'
     end as '성별',

     count(*) as '인원수'
from sawon
  group by deptno, case when substring(jubun,7,1) in ('1','3') then '남'
    else '여'end

 

select 
     deptno as '부서번호',
     case when substring(jubun,7,1) in ('1','3') then '남'
     else '여'
     end as '성별',

     count(*) as '인원수'
from sawon
  group by deptno, case when substring(jubun,7,1) in ('1','3') then '남'
    else '여'end

with rollup; --  각부서별 총인원수와 모든부서 인원수를 나타내준다.

 

select 
     deptno as '부서번호',
     case when substring(jubun,7,1) in ('1','3') then '남'
     else '여'
     end as '성별',

     count(*) as '인원수'
from sawon
  group by deptno, case when substring(jubun,7,1) in ('1','3') then '남'
    else '여'end

with cube; - rollup에 모든부서 인원수에서 남,여 인원수도 나타내준다 즉 rollup < cube

 

select case grouping(deptno) when 1 then '모든부서' --0,1 값이 나오는데 1은 그룹핑 된거
                else deptno end '부서번호',                     -- 즉 1은 null값 
     case grouping(sex) when 1 then '남녀모두'
  else sex end '성별', count(*)
from (select isnull(convert(char,deptno),'인턴') 'deptno',  -- inner view
  case when substring(jubun,7,1) in ('1','3') then '남'
  else '여'
  end as 'sex'
 from sawon
) t
group by deptno,sex
with rollup;

 

select case grouping(deptno) when 1 then '든부서'
  else '모든부서' end '부서번호',
     case grouping(sex) when 1 then '남녀모두'
  else sex end '성별', count(*)
from (select isnull(convert(char,deptno),'인턴') 'deptno',
  case when substring(jubun,7,1) in ('1','3') then '남'
  else '여'
  end as 'sex'
 from sawon) t
group by deptno,sex
with cube;


select name,jik,sal
from sawon
order by jik
compute avg(sal) by jik   --- 직급을 order해뒀기 때문에

 직급별로 avg를 계산한다.


 

 

 

 

반응형

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

UNION ,UNION ALL ,INTERSECT and EXCEPT  (0) 2010.06.18
join & subquery 연습  (0) 2010.06.18
통계를 편리하게 확인  (0) 2010.06.17
ANSI_NULLS NULL값과 비교  (0) 2010.06.08
QUOTED_IDENTIFIER  (0) 2010.06.08
반응형

/* <sp_stat.sql>
정원혁 2003.8.12
설명   :  주어진 테이블의 주어진 컬럼에 대한 통계를 보여준다.
만약 해당 컬럼의 통계가 없다면 새로 생성하고 보여준 후 삭제한다
수정: 2006.6.정원혁
특수 테이블 이름, 컬럼 처리 가능하도록 수정
like 사용하여 발생하던 오류 수정
*/
USE master
GO
IF object_id('dbo.sp_stat') IS NOT NULL 
DROP PROC dbo.sp_stat
GO

CREATE PROC sp_stat
@objname sysname = null
, @colname sysname = null
, @fullscan bit = 0
, @debug bit = 0 --동적 쿼리 문장을 보여주기 위한 디버깅 용도
AS
SET NOCOUNT ON
SET LOCK_TIMEOUT 30000
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

IF @objname IS NULL OR @colname IS NULL
BEGIN 
PRINT '테이블 이름과 컬럼이름이 없습니다.'
RETURN -1
END 

IF LEFT (@objname , 1) <> '['
SET @objname = '['+ @objname + ']'
IF LEFT (@colname , 1) <> '['
SET @colname = '['+ @colname + ']'
IF @debug = 1
select @objname, @colname

--이미 통계가 존재하는지 검사한다
DECLARE @statName sysname 
SET @statName = NULL 
SELECT @statName = i.NAME
FROM sysindexes i
JOIN sysobjects o ON i.id = o.id
WHERE o.NAME = @objname
AND i.NAME = @colname

if @debug = 1
select @statName as statName

IF @statName IS NULL
BEGIN 
DECLARE @sql varchar(2000)
SET @sql='Create Statistics ' + REPLACE(@colname, '[', '[tmp_') + ' on '+@objname+'('+@colname+') '
IF @fullscan = '1' 
SET @sql = @sql + ' WITH FULLSCAN'
IF @debug = 1
PRINT @sql
ELSE
EXECUTE(@sql)

SET @sql='DBCC SHOW_STATISTICS('+@objname+' , '+ REPLACE(@colname, '[', '[tmp_') +')'
IF @debug = 1
PRINT @sql
ELSE
EXECUTE(@sql)

SET @sql='DROP STATISTICS '+@objname+'.'+REPLACE(@colname, '[', '[tmp_') 
IF @debug = 1
PRINT @sql
ELSE
EXECUTE(@sql)
END 
ELSE BEGIN  
SET @sql='DBCC SHOW_STATISTICS('+@objname+', '+@statName+')'
IF @debug = 1
PRINT @sql
ELSE
EXECUTE(@sql)
END
GO


/* 테스트
USE Credit
EXEC sp_stat charge, charge_amt, 1, 1
EXEC sp_stat charge, charge_amt
use northwind
exec sp_stat [order details], ProductID, 0, 1
*/

반응형

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

join & subquery 연습  (0) 2010.06.18
그룹함수  (0) 2010.06.18
ANSI_NULLS NULL값과 비교  (0) 2010.06.08
QUOTED_IDENTIFIER  (0) 2010.06.08
[SQL 2005 GUIDE] 재컴파일 발생 원인 추적하기  (0) 2009.07.25
반응형
USE Northwind

IF (OBJECT_ID('dbo.ListRegionalEmployees') IS NOT NULL)
DROP PROC dbo.ListRegionalEmployees
GO
SET ANSI_NULLS OFF
GO
CREATE PROC dbo.ListRegionalEmployees 
@region nvarchar(30)
AS
SELECT EmployeeID, LastName, FirstName, Region
FROM Employees
WHERE Region = @region
GO
SET ANSI_NULLS ON
GO

EXEC dbo.ListRegionalEmployees NULL

반응형

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

그룹함수  (0) 2010.06.18
통계를 편리하게 확인  (0) 2010.06.17
QUOTED_IDENTIFIER  (0) 2010.06.08
[SQL 2005 GUIDE] 재컴파일 발생 원인 추적하기  (0) 2009.07.25
[SQL 2005 GUIDE] 개체 카탈로그 뷰 - sys.sql_modules  (0) 2009.07.25
반응형

스페이스가 포함된 오브젝트를 참조할 수 있게 해준다.

USE Northwind
SET QUOTED_IDENTIFIER ON
GO
IF OBJECT_ID('dbo.listorders') IS NOT NULL
DROP PROC dbo.listorders
GO
CREATE PROC dbo.listorders
AS
SELECT * FROM "Order Details"
GO
SET QUOTED_IDENTIFIER OFF
GO
EXEC dbo.listorders

반응형
반응형

SQL Server 2000에서 재컴파일 이슈를 분석해 보신 분들은 SP:Recompile 이라는 추적 이벤트를 사용해 보셨을 겁니다.
SQL Server 2005에서는 statement level의 재컴파일 발생을 알려 주는 SQL:StmtRecompile 라는 추적 이벤트가 추가되었습니다.
SP:Recompile 이벤트는 저장 프로시저와 트리거에 대해서만 발생하는 이벤트인데 비하여, SQL:StmtRecompile 이벤트는 저장 프로시저, 트리거 뿐만 아니라 ad-hoc batch에 대해서도 발생하는 이벤트입니다. (ad-hoc batch에는 sp_executesql, prepared queries,  dynamic SQL을 사용하여 실행되는 batch들이 포함됩니다.)
SP:Recompile과 SQL:StmtRecompile의 EventSubClass 컬럼에는 재컴파일이 발생하는 원인을 나타내는 정수값이 저장됩니다.
저장 프로시저의 재컴파일이 발생하는 원인을 확인하고자 하는 경우에는 프로파일러 또는 SQLDIAG로 SP:Recompile 이벤트와
EventSubClass 컬럼을 추가하여 Trace를 수집하여 분석하면 됩니다.
 
EventSubClass 컬럼의 값에 대한 다음 설명을 참고 바랍니다.
 
EventSubClass  재컴파일 원인 
1                      스키마 변경
2                      통계(Statistics) 변경
3                      지연된 컴파일 (Deferred compile).
4                      SET 옵션 변경
5                      임시 테이블 변경
6                      원격 행 집합(Remote rowset) 변경 
7                      FOR BROWSE 권한 변경
8                      Query notification 환경 변경
9                      분할된 뷰(Partitioned view) 변경
10                     커서 옵션 변경
11                     OPTION (RECOMPILE) 사용
 
 
재컴파일 발생 여부는 SQL Re-compilations/sec 성능 카운터와 Sys.dm_exec_query_stats DMV의 plan_generation_num 값을 확인하면 됩니다. plan_generation_num 값이 증가하면 재컴파일이 발생하고 있다는 것을 나타냅니다.
 
 

참고 -
참고로 리컴파일 이슈는 아주 자주 불러지는 sql 에 대해서 더 중요합니다. 배치 작업을 하는 곳에서 컴파일 시간이 30초 라고 해도 실행시간이 1시간 이다 라고 생각하면 이 컴파일 시간을 무시해도 좋지만, 컴파일 하는데 0.4초 정도 나오는데 연속적으로 100번씩 불러지는 프로시져는 반드시 리컴파일 이슈를 확인하셔야 합니다. (참고로 그냥 적어 봅니다.)
반응형
반응형

sys.sql_modules 라는 개체 카탈로그 뷰 사용해 보지 않으셨다면 한번 사용해 보세요.

P, RF, V, TR, FN, IF, TF, R, D 유형의 개체에 대하여 개체별로 하나의 행을 반환합니다.


USE AdventureWorks;

GO

 

SELECT * FROM sys.sql_modules

GO


반응형
반응형

추적과 성능 로그 데이터를 연계 분석하는 방법입니다. 참고하세요.

  1. 추적 데이터를 수집하여 파일 또는 테이블에 저장합니다.

      이 때 StartTime 과 EndTime 컬럼을 포함해야 합니다.

  2. 추적 데이터를 수집하는 동안 동시에 성능 로그 데이터를 수집합니다.

  3. 추적 파일 또는 추적 테이블을 엽니다.

  4. SQL Server 프로파일러 [파일] 메뉴에서 [성능 데이터 가져오기]를 클릭합니다.

  5. [열기] 대화 상자에서 상관 관계를 분석하고자 하는 성능 로그 파일을 선택합니다 .

  6. [성능 카운터 제한 대화 상자 ]에서 추적과 함께 화면에 표시하고자 하는 시스템 모니터 개체와 카운터를

      선택한 다음에 [확인] 버튼을 클릭합니다.

  7. 추적 이벤트 창에서 이벤트를 선택하거나 화살표 키를 사용하여 추적 이벤트 창의 인접 행으로 이동합니다.

     시스템 모니터 데이터 창의 빨간색 세로 막대는 선택한 추적 이벤트와 상관 관계에 있는 성능 로그 데이터를 나타냅니다.

  8. 시스템 모니터 그래프에서 자세히 보고 싶은 시점을 클릭하면, 선택한 시간에 가장 가까운 해당 추적 행이 선택됩니다 .

반응형
반응형

> Link : http://support.microsoft.com/kb/328551/

SQL Server 2000에서 tempdb 경합을 경험하신 DBA라면 추적 플래그 -T1118 에 대하여 알고 계실 겁니다.


추적 플래그 1118은 SGAM contention을 감소시키기 위하여 사용하는 추적 플래그입니다. (참고로 Shared Global Allocation Map 하나에 64000 개의 mixed extent들의 상태 정보가 기록됩니다.)

큰 규모의 시스템에서 빈번하게 호출되는 저장 프로시저들에 임시 테이블과 인덱스를 만드는 DDL 문이 포함되어 있다면 SQL Server 2005에서도 추적 플래그 1118 이 필요하다고 합니다. tempdb 경합이 심하게 발생하면 시스템이 응답하지 않는 것과 같은 심각한 상황이 발생할 수도 있으므로 DBA는 이 내용에 대해 사전에 인지하고 있는 것이 좋습니다.

1. SQL Server 시작 옵션에 추적 플래그 -T1118을 추가합니다.
2. 프로세서의 수와 동일한 숫자만큼 tempdb 데이터 파일 수를 늘립니다. 이 때 tempdb 데이터 파일의 크기는 모두 동일하게 만듭니다. 가령 8 CPU 서버라면 동일한 크기의 tempdb 데이터 파일을 8개가 되도록 데이터 파일을 추가합니다. 로그 파일은 하나인 상태 그대로 유지합니다.
3. 계획휴지 시에 SQL Server를 재시작합니다.

tempdb 성능에 관심 있으신 분은 다음 기술 문서를 꼭 읽어 보세요. 실제로 튜닝 컨설팅을 수행하면서 국내의 대용량 OLTP 시스템들의 경우에 근본적인 튜닝은 저장 프로시저에서 임시 테이블을 사용하지 않도록 수정하여 성능을 개선하였지만, 소스 수정 전에 임시로 tempdb 경합을 완화시키는데에는 추적 플래그 1118 과 tempdb 다중 데이터 파일 구조가 도움이 되었습니다.
반응형
반응형

작년에 MS에서 SQL Server MVP들을 미국에서 열리는 PASS에 보내 주었었는데, PASS 전체 참석자들을 대상으로 하는 공식 세미나가 끝난 다음에 MS에서 MVP들만을 대상으로 SQL Server 2005에 대한 몇 가지 세미나를 해 주었었습니다. 그 세션 중 하나가 tempdb에 대한 내용이었는데 tempdb라는 한 가지 주제를 가지고 한 시간 내내 설명하는 것을 보고, tempdb가 SQL Server 2005에서 보다 중요한 역할을 하게 되었다는 것을 느낄 수 있었습니다.

tempdb 데이터베이스의 크기와 물리적인 배치가 시스템의 성능에 영향을 미친다는 것은 이미 앞에서 말씀드린바 있습니다. tempdb의 기본적인 내용에 대해서는 앞에 올린 글을 참조하시기 바랍니다.

SQL Server 2005에서는 tempdb를 SQL Server 2000에 비해 더 많이 사용합니다. 어떤 기능을 사용하는가에 따라서 SQL Server 2000에서보다 tempdb를 훨씬 더 많이 사용하게 될 수도 있습니다.
그래서 SQL Server 2005에서는 DBA가 시스템을 구성하고 관리할 때 tempdb 관리 작업의 우선 순위가 높아졌다고 할 수 있습니다. tempdb의 작업 부하를 분산하여 성능 향상을 꾀하는 것도 필요하지만 그보다 더 중요한 것은 작업이 원활하게 수행될 수 있도록 tempdb를 적절한 크기로 구성하는 것이 중요합니다. 

Tempdb sizing을 위해서는 어떤 작업을 실행할 때 tempdb에 공간을 필요로 하는지 알아야겠지요 !!!

그렇다면 SQL Server 2005에서 어떤 작업이 tempdb를 사용하는지 알아보겠습니다. 일부 내용은 혹시 제가 잘못 한글로 번역하는 오류를 범할까 염려되어 영어 원문을 그대로 기술하였습니다. 저도 SQL Server 2005를 공부해 가는 사람이라 제가 모르는 부분이 더 있을지 모릅니다. 혹시 아래 기능들 외에 tempdb를 사용하는 작업에 대하여, 또는 tempdb sizing에 대하여 아시는 분은 답글 부탁드립니다.


1. DBCC CHECKDB

2. 내부 개체 
   - work file (해시 조인, SORT_IN_TEMPDB 옵션 사용 시) - CTE
   - work table (커서, 스풀)

3. LOB 변수

4. 서비스 브로커

5. 임시 개체

    1) 전역 임시 테이블, 로컬 임시 테이블

    2) table 변수

    3) 임시 저장 프로시저 

    4) 임시 커서

6. 버전 저장

    1) MARS

    2) 온라인 인덱스 재구성
         - 인덱스 크기의 2 ~ 3배가 필요함 (정렬, 임시 인덱스, 롤백)

    3) Row versioning 
         - [Size of Version Store] = 2 *
            [Version store data generated per minute] *
            [Longest running time (minutes) of your transaction] *
            number of concurrent transactions/users
         - 성능 모니터의 SQL Server 2005:Transactions 성능 개체에 Version Store에
            관련되는 다음과 같은 성능 카운터들이 추가되었습니다.
                - Version Store Size (KB)
                - Version Store unit count
                - Version Store unit creation
                - Version Store unit truncation

    4) 트리거

7. XML

이상입니다.


Version Store에 대해서는 좀 더 심도있는 공부가 필요할 것 같습니다. 성능 모니터의 한글 설명으로는 이해가 잘 되질 않네요. ^ ^
모르는 것이 많아져서 답답할 때가 많지만, 이렇게 끝없이 공부할 게 있고 잡힐 듯 하면서 잡히지 않는 데이터베이스, 참 매력적인 분야인 것 같습니다.

반응형
반응형

SQL Server 의 로컬 서버 이름을 변경하는 방법입니다. 보통 컴퓨터 이름이 변경된 경우에 로컬 서버의 이름을 동일하게 변경하고자 하여 다음과 같은 작업을 수행하게 됩니다. 참고로 sp_addserver는 원격 서버 또는 로컬 SQL Server 인스턴스 이름을 정의하는데 사용할 수 있습니다만, 원격 서버를 등록하는 경우에는 sp_addserver 대신 sp_addlinkedserver를 사용하라고 온라인 설명서에 나와 있습니다. 그런데 로컬 SQL Server 인스턴스 이름을 등록할 때에는 여전히 sp_addserver를 사용하는 것이 최적의 방법인지에 대해서는 설명이 없네요. ^ ^

SQL Server 2005에서 로컬 SQL Server 인스턴스 이름을 변경하는 더 좋은 방법을 아시는 분은 답글 부탁합니다. 


SELECT @@SERVERNAME;

GO

/*

SUNGHEE\SS2005

*/

 

 

EXEC sp_dropserver 'SUNGHEE\SS2005'

GO

/*

명령이완료되었습니다.

*/

 

EXEC sp_addserver 'TEST\SS2005', 'local'

GO

/*

명령이완료되었습니다.

*/

 

SELECT @@SERVERNAME

GO

/*

SUNGHEE\SS2005

*/

 

 

SHUTDOWN

GO

/*

로그인SUNGHEE\Administratorrequest에의해서버가종료됩니다.

SQL Server가이프로세스를종료합니다.

*/

 

 

-- SQL Server 서비스재시작

 

 

SELECT @@SERVERNAME

GO

/*

TEST\SS2005

*/

 

 


별로 중요한 건 아니지만 참고로 한 마디...


SERVERPROPERTY 함수의 ServerName 속성과 @@SERVERNAME은 비슷한 정보를 반환합니다. ServerName 속성은 Windows 서버와 고유한 서버 인스턴스를 구성하는 인스턴스 이름을 제공합니다. @@SERVERNAME은 현재의 로컬 서버 이름을 제공합니다. 기본 서버 이름을 바꾸지 않은 상태에서는 ServerName 속성과 @@SERVERNAME은 같은 정보를 반환하지만, 위와 같이 로컬 서버 이름을 변경한 경우에는 다음과 같이 SERVERPROPERTY 함수의 ServerName 속성값과 @@SERVERNAME 값이 달라집니다. 별로 중요한 사항은 아니지만 SERVERPROPERTY('ServerName') 을 실행한 결과를 보시고 왜 로컬 서버 이름이 안 바뀌는지 고민하시는 분이 계실까봐 얘기해 봤습니다.



SELECT SERVERPROPERTY('ServerName')

GO

/* 결과:

SUNGHEE\SS2005

*/

 

 

SELECT @@SERVERNAME

GO

/* 결과

TEST\SS2005

*/

 


반응형
반응형

언젠가 SQL Server 2000에 대하여 다음과 같은 질문을 받은 적이 있습니다. DBCC 명령어를 실행하였는데 실행했다는 메시지만 나오니까 조금 황당했었나 봅니다. SQL Server 2005에서는 확실하게 결과를 제공하네요. 기뻐하세요. ㅋㅋㅋ


[질문]
DBCC SHOWCONTIG 를 실행했는데 결과가 나오지 않는데 이유가 뭘까요?
테이블에 인덱스가 없어서인가요?

[답변]
테이블에 데이터가 없으면 결과가 나오지 않습니다. 인덱스가 있건 없건 상관없이 데이터가 없으면 결과 행이 반환되지 않고 데이터가 한 건이라도 있으면 결과 행들이 반환됩니다.

SQL Server 2000에서는 다음과 같이 테이블에 행이 한 건도 없으면 "DBCC 실행이 완료되었습니다. DBCC에서 오류 메시지를 출력하면 시스템 관리자에게 문의하십시오." 라는 메시지만 반환되고 결과 행은 반환되지 않았습니다.

USE tempdb

GO

 

CREATE TABLE t1 (c1 int PRIMARY KEY)

GO

 

DBCC SHOWCONTIG ('t1')

GO

/*

DBCC 실행이완료되었습니다. DBCC에서오류메시지를출력하면시스템관리자에게문의하십시오.

*/

 

 

 

SQL Server 2005에서는테이블에데이터가없어도결과행이반환되는군요.

이제헷갈리는분들이줄어들겠네요. ^ ^

 

 

USE tempdb

GO

 

CREATE TABLE t1 (c1 int PRIMARY KEY)

GO

 

DBCC SHOWCONTIG ('t1')

GO

/* 결과

 

DBCC SHOWCONTIG() 't1' 테이블을검색하는중...

테이블: 't1'(165575628); 인덱스ID: 1, 데이터베이스ID: 2

TABLE 수준검색을수행했습니다.

- 검색한페이지................................: 0

- 검색한익스텐트..............................: 0

- 익스텐트스위치..............................: 0

- 익스텐트당평균페이지수........................: 0.0

- 검색밀도[최적:실제].......: 100.00% [0:0]

- 논리검색조각화상태..................: 0.00%

- 익스텐트검색조각화상태...................: 0.00%

- 페이지당사용가능한평균바이트수.....................: 0.0

- 평균페이지밀도(전체).....................: 0.00%

DBCC 실행이완료되었습니다. DBCC에서오류메시지를출력하면시스템관리자에게문의하십시오.

 

*/

 

반응형
반응형

SQL Server에 대한 기술 문서를 보다 보면 캐시라는 용어도 자주 나오고 풀이라는 용어도 자주 접하게 됩니다. 특히 성능이나 아키텍처에 관한 문서에 이런 용어들이 자주 나오는데, 실제로 이런 용어들을 사용하면서 확실하게 이 두 가지가 어떻게 다른지 잘 모르고 사용하는 경우가 많습니다. 저도 잘 모릅니다만, 자료에 나와 있는 캐시와 풀의 비교 설명을 옮겨 봅니다. 저는 다섯번째 얘기가 가장 마음에 와 닿네요. ^ ^


1. 캐시 (Cache)

- 이기종 데이터를 캐싱하는 메커니즘이며, 각각의 엔트리에 대하여 정해진 비용이 있음

- 대개의 경우 엔트리별로 상태가 관리됨

- 엔트리에 대해서 lifetime 제어가 구현되어 있음

- LRU 정책을 제공함

- 캐싱된 데이터의 유형에 따라 다르지만, 하나의 엔트리를 동시에 다중의 클라이언트들이 사용 가능함

- 예: 프로시저 캐시, 데이터 캐시 (버퍼)


2. 풀 (Pool)

- 동종 데이터를 캐싱하는 메커니즘

- 상태 정보를 가지지 않음

- lifetime에 대한 제한적인 제어

- 어떤 시점에는 오직 한 클라이언트만이 사용 가능 : 하나의 엔트리가 풀에서 선택되어 사용되면 그 엔트리는 풀에서 제거되며, 그 엔트리가 다시 풀로 되돌아올 때까지는 풀이 그 엔트리에 대한 제어권을 가지지 못하는 구조임.

- 예: 네트쿼크 버퍼 풀
반응형
반응형
서버 메모리 구성값을 설정하는데 있어서 가장 중요하게 고려해야 할 사항은 페이징이 발생하지 않도록 해야 한다는 것입니다. 그러기 위해서는, 모든 어플리케이션이 사용하는 메모리의 크기의 합이 전체 시스템 메모리보다 작도록 구성해야 합니다.

SQL Server 2005에서의 메모리 구성에 관하여 참고사항을 소개하고자 합니다.

1. max server memory 설정

SQL Server는 버퍼 풀 외에 SQL Server가 추가로 메모리를 필요로 한다는 것을 염두에 두고 ‘max server memory’를 적절하게 구성하여야 한답니다. 특히 IA64의 경우에는 thread stack size 4MB이기 때문에 ‘max worker threads’의 값이 크면 버퍼 풀 외에 SQL Server가 추가로 필요로 하는 메모리의 양이 많이 커지므로 유의하시기 바랍니다. 
 

SQL Server max server memory 계산 식:

max server memory = 전체 시스템 메모리

- max worker threads X thread stack size

- 운영 체제/다른 응용 프로그램이 사용하는 메모리 (대략 2-4 GB)

 

Thread Stack Size:

 

Thread Stack Size

32 bit

512 K

X64

2 MB

IA64

4 MB

 

예를 들어 IA64 64GB RAM 시스템에서 max worker threads 1024라면 SQL Server ‘max server memory’ 다음과 같이 계산될 있습니다. 만일 실제 메모리가 64 GB인데 SQL Server 전용 시스템이라고 하여 운영 체제를 위하여 2 GB 남겨 두고, SQL Server ‘max server memory’ 62 GB 구성하면 Thread Memory 부족하게 되는 문제가 발생하게 됩니다.

64GB - 1024 X 4 MB - 4 GB (운영 체제/다른 응용 프로그램) = 56 GB


이런 공식을 사용하여 얻은 결과를 구성값에 적용하고, 모니터링을 통해 Available Physical Memory가 1GB 정도 남을 수 있도록 다시 max server size를 변경해 주는 것이 좋다고 합니다. 이 내용은 MS 기술지원엔지니어로부터 들은 이야기입니다.
 

2. AWE

64 bit SQL Server 2005에서는 디폴트로 시스템이 AWE를 활성화해 줍니다.

참고로 다음 내용도 한번 읽어 보시기 바랍니다.

Address Windowing Extensions and Microsoft Windows 2000 Datacenter Server:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dngenlib/html/awewindata.asp

 
3. min server memory

64 bit SQL Server 2000에서는 'min server memory' 구성값을 설정하면 SQL Server 서비스가 시작될 때 'min server memory'에 지정된 만큼의 메모리를 확보하였지만, 64 bit SQL Server 2005에서는 최소로 필요한 메모리만 확보하고 서비스를 시작하는 것으로 변경되었습니다.


4. 메모리 DMV

SQL Server 2005에서는 다양한 메모리 DMV가 지원됩니다. 이 DMV들이 문제를 해결하거나 시스템을 진단하는데 있어서 유용한 정보를 제공해 줄 것으로 기대됩니다.


5. SQL Server 2005의 메모리 관리자 구성 요소

- Memory Nodes
- Memory Clerks
- Page allocators
- Memory Objects
- Resource Monitor
- Memory Broker

각각의 구성 요소에 대해서는 좀 더 깊이있는 공부가 필요할 것 같습니다.
반응형
반응형

text, image 데이터 형식에 비해 큰 값 데이터 형식이 가지는 장점 중 한가지가 큰 값 데이터 형식에는 문자열에 사용 가능한 문자열 함수들을 사용할 수 있다는 것입니다. 그렇지만 문자열 함수를 사용할 때 유의해야 할 점이 있습니다.

 

명시적으로 그 문자열 함수를 적용하고자 하는 식이 varchar(max)라는 것을 알려 주지 않으면, 문자열 함수는 기본적으로 식을 문자열 데이터 형식으로 간주한다는 점입니다.

 

예를 들어 다음 스크립트를 보면 @max 라는 로컬 변수는 varchar(max)로 정의되어 있습니다. 그런데 replicate 함수를 사용하여 10000 바이트 크기의 문자열을 만들어서 @max 변수에 저장하려고 하면 실제로는 @max 변수에 8천 바이트만 저장됩니다. 문자열 함수의 결과를 저장할 그릇을, 문자열 데이터 형식을 기준으로 준비하는 것으로 판단됩니다. 그래서 함수 결과가 문자열 데이터 형식의 최대 크기인 8000 바이트까지만 인식하는 거죠.

 

 

 

DECLARE @max varchar(max)

SELECT @max = replicate('1234567890', 1000)

SELECT @max, datalength(@max)

GO

--> 8000 바이트

 

 

만일 다음과 같이 CAST('1234567890' AS varchar(max) 라고, 식이 varchar(max)라는 것을 SQL Server에게 미리 알려 주면 이 replicate 함수는 다음과 같이 10000 바이트를 정상적으로 처리합니다.

 

 

DECLARE @max varchar(max)

SELECT @max = replicate(CAST('1234567890' AS varchar(max)), 1000)

SELECT @max, datalength(@max)

GO

--> 10000 바이트

 

 

 

문자열 결합 연산자인 + 도 마찬가지입니다.

다음 예에서와 같이 replicate 함수를 적용한 다음에 varchar(max)로 변환해 보았자 이미 8000 바이트까지만 인식되었기 때문에 데이터가 8천 바이트까지만 인식됩니다.

 

 

DECLARE @max varchar(max)

SELECT @max = CAST(replicate('max test 1', 800) +

                   replicate('max test 2', 800) AS varchar(max))

SELECT datalength(@max)

GO

--> 8000 바이트

 

 

다음과 같이 + 연산자를 적용할 식 중 하나라도 varchar(max)로 정의하거나, + 연산자를 적용할 식 중 하나에 CAST 함수를 적용하면 원하는 결과를 얻을 수 있습니다.

DECLARE @max1 varchar(max), @max2 varchar(max), @max3 varchar(max)

SELECT @max1 = replicate('max test 1', 800)

SELECT @max2 = replicate('max test 2', 800)

SELECT @max3 = @max1 + @max2

SELECT datalength(@max3)

GO

-- 16000

DECLARE @max varchar(max)

SELECT @max = CAST(replicate('max test 1', 800) AS varchar(max))

  + replicate('max test 2', 800)

SELECT datalength(@max)

GO

-- 16000

 


반응형
반응형

큰 값 데이터 형식에 대한 기본적인 내용은 이미 앞에서 한번 소개드렸습니다. 오늘은 varchar(max)를 대상으로 테스트해 본 스크립트를 올려 봅니다.

 

다음은 varchar(max)가 실제로 데이터 행과 함께 저장되는지를 제 눈으로 확인하기 위해 DBCC PAGE DBCC EXTENTINFO 명령어를 사용하여 작성해 본 스크립트입니다. 다음 스크립트를 테스트해 보면 varchar(max) 데이터 형식의 내부 표현을 확인할 수 있습니다.

 

 

 

CREATE DATABASE NewDatatype

GO

USE NewDatatype

GO

CREATE TABLE BigTable (id int, col1 varchar(25),

     col2 varchar(max), col3 varchar(max))

GO

INSERT INTO BigTable VALUES (1, 'Row1', 'AAAAAAAAAA', 'aaaaaaaaaa')

INSERT INTO BigTable VALUES (2, 'Row2', 'BBBBBBBBBB', 'bbbbbbbbbb')

GO

SELECT * FROM sysindexes

WHERE id=object_id('BigTable')

GO

DBCC EXTENTINFO ('NewDatatype', 'BigTable')

GO

--> file_id = 1

--> PAGE_id = 40

DBCC TRACEON (3604)

GO

DBCC PAGE ('NewDatatype', 1, 40, 3)

GO

 

UPDATE BigTable SET col2 = replicate('A', 8000) WHERE id = 1;

GO

DBCC PAGE ('NewDatatype', 1, 40, 3)

GO

 

UPDATE BigTable SET col2 = replicate('B', 4000) WHERE id = 2;

GO

DBCC EXTENTINFO ('NewDatatype', 'BigTable')

GO

DBCC PAGE ('NewDatatype', 1, 40, 3)

GO

DBCC PAGE ('NewDatatype', 1, 80, 3)

GO

 

 

 

위의 스크립트를 활용하여 'large value types out of row' 옵션을 적용하는 경우에는 내부적으로 어떻게 저장되는지 확인해 보겠습니다.

 

'large value types out of row' 의 값이 1이면, varchar(max), nvarchar(max), varbinary(max), xml 컬럼들이 행의 외부에 저장되며 행의 내부에는 root에 대한 16바이트 포인터를 가집니다. 0이면 varchar(max), nvarchar(max), varbinary(max), xml 값이 데이터 행에 직접 저장됩니다.

 

 

 

-- 1) 'large value types out of row' 옵션 활성화

EXEC sp_tableoption N'BigTable', 'large value types out of row', 'ON';

GO

 

 

DBCC PAGE ('NewDatatype', 1, 40, 3)

GO

 

-- 2) UPDATE를 실행해야 실제로 옵션 활성화한 효과가 적용됩니다.

UPDATE BigTable SET col2 = replicate('A', 20)

WHERE id = 1;

GO

DBCC PAGE ('NewDatatype', 1, 40, 3)

GO

DBCC EXTENTINFO ('NewDatatype', 'BigTable')

GO

DBCC PAGE ('NewDatatype', 1, 89, 3)

GO

 

 

-- 3) 'large value types out of row' 옵션 비활성화

EXEC sp_tableoption N'BigTable', 'large value types out of row', 'OFF';

GO

 

 
반응형
반응형

SQL Server 2005에는 xml 이라는 데이터 형식이 새롭게 추가되었습니다.
xml
데이터 형식의 도입으로 XML document fragment SQL Server 데이터베이스에 저장할 수 있게 되었습니다. xml 데이터 유형이 있다는 걸 기억해 두시고, xml 데이터 형식을 활용하시기 바랍니다. 참고로 xml 데이터 형식에는 최대 2GB까지 저장할 수 있습니다.

xml
형식의 변수는 다음과 같이 정의합니다.

 

declare @x xml

 

 

xml 열은 다음과 같이 정의하면 됩니다.

 

CREATE TABLE XmlTest (id int identity, xcol xml);

 

 

XQuery를 사용하면 xml 형식의 , 매개 변수변수에 저장된 XML 인스턴스를 쿼리할 수 있습니다. 또한 XML DML(XML 데이터 조작 언어)을 사용하여 XML 인스턴스에 업데이트를 적용할 수도 있습니다.

xml
데이터 형식을 사용하면 열에 데이터가 저장될 때 well-formed인지 SQL Server가 점검하고 만일 well-formed가 아닌 경우에는 데이터 저장이 실패합니다. 예를 들어 다음과 같이 시작 태그와 끝 태그의 짝이 맞지 않는 데이터는 INSERT가 실패합니다

 

INSERT INTO XmlTest VALUES ('');

 

xml 데이터는 xml 데이터 형식을 사용하는 것이 데이터 유효성 측면이나 쿼리의 편의성 측면에서 좋습니다. 만일 xml 데이터 형식을 몰라서 varchar로 정의하여 사용하고 있는 테이블의 열을 max로 변경하고 싶다면 다음과 같이 ALTER TABLE을 사용하여 변경 가능합니다. 열 유형을 문자열에서 형식화된 xml로 변경하는 경우에는 열에 이미 저장되어 있는 문서의 유효성을 점검하므로, 이와 같이 문자열을 xml 형식으로 변경하고자 하는 경우에는 xml 문서가 올바른 형식이어야 합니다

 

CREATE TABLE T (Col1 int primary key, Col2 nvarchar(max))

GO

-- 데이터INSERT

ALTER TABLE T ALTER COLUMN Col2 xml

GO

 

 

 

 

xml 열에 저장된 데이터는 다양한 형태로 조회 가능합니다.

 

SELECT xcol FROM XmlTest for xml auto, type, xmlschema

 

 

 

이미 CHECK 제약 조건에서 설명한 사항인데 xml 형식의 열에 제약 조건을 정의할 수는 있지만 제약 조건을 지정할 때 XML 데이터 유형 메서드를 사용할 수는 없습니다. 사용자 정의 함수인 래퍼를 만들어 xml 데이터 유형 메서드를 래핑하고 CHECK 제약 조건에 사용자 정의 함수를 지정해야 한다는 거 잊지 마세요예제는 CHECK 제약 조건에 있으므로 참고하세요.

 

반응형
반응형

 

SQL Server 2005에서 대기(Wait)를 점검하는데 사용할 수 있는 저장 프로시저 스크립트입니다.

참고하세요.

사용하시기 전에 주석 내용 꼭 읽어 보시구요.


 

 

 

IF EXISTS (SELECT * from sys.objects where OBJECT_ID = OBJECT_ID(N'[dbo].[track_waitstats_2005]') and OBJECTPROPERTY(OBJECT_ID, N'IsProcedure') = 1)

 DROP PROCEDURE [dbo].[track_waitstats_2005]

go

CREATE proc [dbo].[track_waitstats_2005] (@num_samples int=10

               ,@delay_interval int=1

               ,@delay_type nvarchar(10)='minutes'

               ,@TRUNCATE_history nvarchar(1)='N'

               ,@clear_waitstats nvarchar(1)='Y')

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

--

-- T. Davidson

-- @num_samples is the number of times to capture waitstats, default is 10 times

-- default delay interval is 1 minute

-- delaynum is the delay interval - can be minutes or seconds

-- delaytype specIFies whether the delay interval is minutes or seconds

-- CREATE waitstats TABLE IF it doesn't exist, otherwise TRUNCATE

-- Revision: 4/19/05

--- (1) added object owner qualIFier

--- (2) optional parameters to TRUNCATE history and clear waitstats

             SET NOCOUNT ON

             IF NOT EXISTS (SELECT 1 from sys.objects where OBJECT_ID = OBJECT_ID ( N'[dbo].[waitstats]') and OBJECTPROPERTY(OBJECT_ID, N'IsUserTABLE') = 1)

              CREATE TABLE [dbo].[waitstats]

                           (

                                        [wait_type] nvarchar(60) NOT NULL,

                                        [waiting_tasks_count] bigint NOT NULL,

                                        [wait_time_ms] bigint NOT NULL,

                                        [max_wait_time_ms] bigint NOT NULL,

                                        [signal_wait_time_ms] bigint NOT NULL,

                                        now datetime NOT NULL default getdate()

                           )

             IF LOWER(@TRUNCATE_history) NOT IN (N'y',N'n')

              BEGIN

                           RAISERROR ('valid @TRUNCATE_history values are ''y'' or ''n''',16,1) WITH NOWAIT

              END

             IF LOWER(@clear_waitstats) NOT IN (N'y',N'n')

              BEGIN

                           RAISERROR ('valid @clear_waitstats values are ''y'' or ''n''',16,1) WITH NOWAIT

              END

             IF LOWER(@TRUNCATE_history) = N'y'

              TRUNCATE TABLE dbo.waitstats

 

             IF LOWER (@clear_waitstats) = N'y'

              DBCC sqlperf ([sys.dm_os_wait_stats],clear) with no_infomsgs -- clear out waitstats

 

             DECLARE @i int,@delay varchar(8),@dt varchar(3), @now datetime, @totalwait numeric(20,1)

              ,@ENDtime datetime,@BEGINtime datetime

              ,@hr int, @min int, @sec int

             SELECT @i = 1

             SELECT @dt = CASE LOWER(@delay_type)

              WHEN N'minutes' THEN 'm'

              WHEN N'minute' THEN 'm'

              WHEN N'min' THEN 'm'

              WHEN N'mi' THEN 'm'

              WHEN N'n' THEN 'm'

              WHEN N'm' THEN 'm'

              WHEN N'seconds' THEN 's'

              WHEN N'second' THEN 's'

              WHEN N'sec' THEN 's'

              WHEN N'ss' THEN 's'

              WHEN N's' THEN 's'

              ELSE @delay_type

             END

             IF @dt NOT IN ('s','m')

             BEGIN

              RAISERROR ('delay type must be either ''seconds'' or ''minutes''',16,1) WITH NOWAIT

              RETURN

             END

             IF @dt = 's'

             BEGIN

              SELECT @sec = @delay_interval % 60, @min = CAST((@delay_interval / 60) as int), @hr = CAST((@min / 60) as int)

             END

             IF @dt = 'm'

             BEGIN

              SELECT @sec = 0, @min = @delay_interval % 60, @hr = CAST((@delay_interval / 60) as int)

             END

             SELECT @delay= RIGHT('0'+ convert(varchar(2),@hr),2) + ':' +

              + RIGHT('0'+convert(varchar(2),@min),2) + ':' +

              + RIGHT('0'+convert(varchar(2),@sec),2)

             IF @hr > 23 or @min > 59 or @sec > 59

             BEGIN

              SELECT 'delay interval and type: ' + convert (varchar(10),@delay_interval) + ',' + @delay_type + ' converts to ' + @delay

              RAISERROR ('hh:mm:ss delay time canNOT > 23:59:59',16,1) WITH NOWAIT

              RETURN

             END

             WHILE (@i <= @num_samples)

             BEGIN

                SELECT @now = getdate()

                                                     insert into [dbo].[waitstats] ([wait_type], [waiting_tasks_count], [wait_time_ms], [max_wait_time_ms], [signal_wait_time_ms], now)

                SELECT [wait_type], [waiting_tasks_count], [wait_time_ms], [max_wait_time_ms], [signal_wait_time_ms], @now

                           from sys.dm_os_wait_stats

                insert into [dbo].[waitstats] ([wait_type], [waiting_tasks_count], [wait_time_ms], [max_wait_time_ms], [signal_wait_time_ms], now)

                           SELECT 'Total',SUM([waiting_tasks_count]), SUM([wait_time_ms]), 0, SUM([signal_wait_time_ms]),@now

                           from [dbo].[waitstats]

                           where now = @now

                SELECT @i = @i + 1

                waitfor delay @delay

             END

--- CREATE waitstats report

EXECUTE dbo.get_waitstats_2005

GO

 

CREATE proc [dbo].[get_waitstats_2005] (
                @report_format varchar(20)='all', 
                @report_order varchar(20)='resource')
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 will create waitstats report listing wait types by 
-- percentage. 
--     (1) total wait time is the sum of resource & signal waits, 
--            @report_format='all' reports resource & signal
--    (2) Basics of execution model (simplified)
--        a. spid is running then needs unavailable resource, moves to 
--         resource wait list at time T0
--        b. a signal indicates resource available, spid moves to 
--         runnable queue at time T1
--        c. spid awaits running status until T2 as cpu works its way
--         through runnable queue in order of arrival
--    (3) resource wait time is the actual time waiting for the
--        resource to be available, T1-T0
--    (4) signal wait time is the time it takes from the point the 
--        resource is available (T1)
--        to the point in which the process is running again at T2. 
--        Thus, signal waits are T2-T1
--    (5) Key questions: Are Resource and Signal time significant?
--        a. Highest waits indicate the bottleneck you need to solve 
--          for scalability
--        b. Generally if you have LOW% SIGNAL WAITS, the CPU is 
--         handling the workload e.g. spids spend move through 
--         runnable queue quickly
--        c. HIGH % SIGNAL WAITS indicates CPU can't keep up, 
--         significant time for spids to move up the runnable queue 
--         to reach running status
--     (6) This proc can be run when track_waitstats is executing
--
-- Revision 4/19/2005
-- (1) add computation for CPU Resource Waits = Sum(signal waits / 
--                                    total waits)
-- (2) add @report_order parm to allow sorting by resource, signal 
--     or total waits
--
set nocount on

declare @now datetime, 
        @totalwait numeric(20,1), 
        @totalsignalwait numeric(20,1), 
        @totalresourcewait numeric(20,1),
        @endtime datetime,@begintime datetime,
        @hr int, 
        @min int, 
        @sec int

if not exists (select 1 
                from sysobjects 
                where id = object_id ( N'[dbo].[waitstats]') and 
                      OBJECTPROPERTY(id, N'IsUserTable') = 1)
begin
        raiserror('Error [dbo].[waitstats] table does not exist',
                 16, 1) with nowait
        return
end

if lower(@report_format) not in ('all','detail','simple')
    begin
        raiserror ('@report_format must be either ''all'',
                    ''detail'', or ''simple''',16,1) with nowait
        return
    end
if lower(@report_order) not in ('resource','signal','total')
    begin
        raiserror ('@report_order must be either ''resource'', 
            ''signal'', or ''total''',16,1) with nowait
        return
    end
if lower(@report_format) = 'simple' and lower(@report_order) <> 'total'
    begin
        raiserror ('@report_format is simple so order defaults to 
''total''',
                        16,1) with nowait
        select @report_order = 'total'
    end


select  
    @now=max(now),
    @begintime=min(now),
    @endtime=max(now)
from [dbo].[waitstats] 
where [wait_type] = 'Total'

--- subtract waitfor, sleep, and resource_queue from Total
select @totalwait = sum([wait_time_ms]) + 1, @totalsignalwait = 
sum([signal_wait_time_ms]) + 1 
from waitstats 
where [wait_type] not in (
        'CLR_SEMAPHORE',
        'LAZYWRITER_SLEEP',
        'RESOURCE_QUEUE',
        'SLEEP_TASK',
        'SLEEP_SYSTEMTASK',
        'Total' ,'WAITFOR', 
        '***total***') and 
    now = @now

select @totalresourcewait = 1 + @totalwait - @totalsignalwait

-- insert adjusted totals, rank by percentage descending
delete waitstats 
where [wait_type] = '***total***' and 
now = @now

insert into waitstats 
select 
    '***total***',
    0,@totalwait,
    0,
    @totalsignalwait,
    @now 

select 'start time'=@begintime,'end time'=@endtime,
       'duration (hh:mm:ss:ms)'=convert(varchar(50),@endtime-
@begintime,14),
       'report format'=@report_format, 'report order'=@report_order

if lower(@report_format) in ('all','detail') 
begin
----- format=detail, column order is resource, signal, total. order by 
resource desc
    if lower(@report_order) = 'resource'
        select [wait_type],[waiting_tasks_count],
            'Resource wt (T1-T0)'=[wait_time_ms]-[signal_wait_time_ms],
            'res_wt_%'=cast (100*([wait_time_ms] - 
                    [signal_wait_time_ms]) /@totalresourcewait as 
numeric(20,1)),
            'Signal wt (T2-T1)'=[signal_wait_time_ms],
            'sig_wt_%'=cast (100*[signal_wait_time_ms]/@totalsignalwait as 
numeric(20,1)),
            'Total wt (T2-T0)'=[wait_time_ms],
            'wt_%'=cast (100*[wait_time_ms]/@totalwait as numeric(20,1))
        from waitstats 
        where [wait_type] not in (
                'CLR_SEMAPHORE',
                'LAZYWRITER_SLEEP',
                'RESOURCE_QUEUE',
                'SLEEP_TASK',
                'SLEEP_SYSTEMTASK',
                'Total', 
                'WAITFOR') and
                now = @now
        order by 'res_wt_%' desc

----- format=detail, column order signal, resource, total. order by signal
desc
    if lower(@report_order) = 'signal'
        select    [wait_type],
                [waiting_tasks_count],
                'Signal wt (T2-T1)'=[signal_wait_time_ms],
                'sig_wt_%'=cast (100*[signal_wait_time_ms]/@totalsignalwait 
                as numeric(20,1)),
                'Resource wt (T1-T0)'=[wait_time_ms]-[signal_wait_time_ms],
                'res_wt_%'=cast (100*([wait_time_ms] - 
                        [signal_wait_time_ms]) /@totalresourcewait as 
numeric(20,1)),
                'Total wt (T2-T0)'=[wait_time_ms],
                'wt_%'=cast (100*[wait_time_ms]/@totalwait as 
numeric(20,1))
        from waitstats 
        where [wait_type] not in (
                    'CLR_SEMAPHORE',
                    'LAZYWRITER_SLEEP',
                    'RESOURCE_QUEUE',
                    'SLEEP_TASK',
                    'SLEEP_SYSTEMTASK',
                    'Total', 
                    'WAITFOR') and
                    now = @now
        order by 'sig_wt_%' desc

----- format=detail, column order total, resource, signal. order by total
desc
    if lower(@report_order) = 'total'
        select 
            [wait_type],
            [waiting_tasks_count],
            'Total wt (T2-T0)'=[wait_time_ms],
            'wt_%'=cast (100*[wait_time_ms]/@totalwait as numeric(20,1)),
            'Resource wt (T1-T0)'=[wait_time_ms]-[signal_wait_time_ms],
            'res_wt_%'=cast (100*([wait_time_ms] - 
                [signal_wait_time_ms]) /@totalresourcewait as numeric(20,1)),
            'Signal wt (T2-T1)'=[signal_wait_time_ms],
            'sig_wt_%'=cast (100*[signal_wait_time_ms]/@totalsignalwait as
numeric(20,1))
        from waitstats 
        where [wait_type] not in (
                'CLR_SEMAPHORE',
                'LAZYWRITER_SLEEP',
                'RESOURCE_QUEUE',
                'SLEEP_TASK',
                'SLEEP_SYSTEMTASK',
                'Total',
                'WAITFOR') and
                now = @now
        order by 'wt_%' desc
end
else
---- simple format, total waits only
    select 
        [wait_type],
        [wait_time_ms],
        percentage=cast (100*[wait_time_ms]/@totalwait as numeric(20,1))
    from waitstats 
    where [wait_type] not in (
                    'CLR_SEMAPHORE',
                    'LAZYWRITER_SLEEP',
                    'RESOURCE_QUEUE',
                    'SLEEP_TASK',
                    'SLEEP_SYSTEMTASK',
                    'Total', 
                    'WAITFOR') and
                now = @now
    order by percentage desc

---- compute cpu resource waits
select 
    'total waits'=[wait_time_ms],
    'total signal=CPU waits'=[signal_wait_time_ms],
    'CPU resource waits % = signal waits / total waits'=
            cast (100*[signal_wait_time_ms]/[wait_time_ms] as
numeric(20,1)), 
    now
from [dbo].[waitstats]
where [wait_type] = '***total***'
order by now
go 
 

EXEC dbo.track_waitstats_2005 @num_samples=20

        ,@delay_interval=30

        ,@delay_type='s'

        ,@TRUNCATE_history='y'

        ,@clear_waitstats='y'

GO

 

반응형
반응형

기본적으로 데이터베이스 엔진의 기본 인스턴스는 TCP 포트 1433에서 수신합니다. 그러나, 1433 포트는 보안을 위하여 변경하는 것이 좋습니다.

 

TCP 포트 확인한 , 변경하기

1.       시작 a SQL Server 2005 a Configuration Tools a SQL Server Configuration Manager 실행합니다.

2.       왼쪽 메뉴에서 MSSQLSERVER 대한 프로토콜을 선택합니다.

3.       오른쪽 메뉴에서 TCP/IP 커서를 대고 마우스 오른쪽 버튼을 클릭한 , 속성을 선택합니다.

4.       TCP/IP 등록 정보 창이 나타납니다.

5.       TCP 포트 열의 1433 원하는 값으로 변경한 , [확인] 클릭합니다.

 

반응형
반응형

fn_trace_gettable 함수를 사용하면 추적 파일을 SQL Server 프로파일러에서 로드 가능한 테이블로 복사할 있습니다.
추적 파일을 테이블로 복사하면 T-SQL 활용하여 다양한 분석이 가능하므로 편리합니다. 

 

추적 파일을 테이블로 복사하기

SELECT IDENTITY(int, 1, 1) AS SeqNo, * INTO temp_trc

FROM fn_trace_gettable('c:\temp\my_trace.trc', default);

GO

 

반응형
반응형

 

다음에 있는 ekdmadp sp_trace_stop sp_trace_start 실행한 추적(Trace) 중지하는 저장 프로시저입니다.

 

n       추적을 중지하는 저장 프로시저의 예제 스크립트 : sp_trace_stop

USE master

GO

CREATE PROCEDURE sp_trace_stop @TraceName sysname='trace'

AS

SET NOCOUNT ON

 

-- 변수를 선언한다

DECLARE @TraceId int 

DECLARE @TraceFileName sysname

 

-- 추적 목록을 확인하여, 추적을 중지합니다

IF OBJECT_ID('tempdb..TraceQueueList') IS NOT NULL BEGIN

    SELECT @TraceId = TraceID, @TraceFileName=TraceFile

FROM tempdb..TraceQueueList

    WHERE TraceName = @TraceName

 

    IF @@ROWCOUNT<>0 BEGIN

        EXEC sp_trace_setstatus @TraceId, 0

        EXEC sp_trace_setstatus @TraceId, 2

        DELETE tempdb..TraceQueueList

WHERE TraceName = @TraceName

        PRINT 'Trace is stopped. '

+ 'The trace output file name is '+@TraceFileName

    END

    ELSE

        PRINT 'No active traces.'

END

ELSE

    PRINT 'No active traces.'

 

RETURN 0

GO

 

/* 실행하기 */

EXEC sp_trace_stop

GO 

 

반응형
반응형

다음은 추적 스크립팅을 저장 프로시저화한 예제 스크립트입니다. 시스템의 환경에 적합하도록 수정 보완하여 활용하기 바랍니다.

 

n       추적을 시작하는 저장 프로시저의 예제 스크립트 : sp_trace_start

USE master

GO

CREATE PROCEDURE sp_trace_start @TraceFileName sysname=NULL,

@TraceName sysname='trace',

@Options int=2, -- TRACE_FILE_ROLLOVER

@MaxFileSize bigint=5,

@StopTime datetime=NULL,

@Events varchar(300)=

'10,12',

--  10 - RPC:Completed

--  12 - SQL:BatchCompleted

@Cols varchar(300)=

'1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,',

-- 모든 이벤트

@IncludeFilter sysname=NULL,

@ExcludeFilter sysname=NULL

AS

SET NOCOUNT ON

-- 변수 선언

DECLARE @TraceId int

DECLARE @On bit

DECLARE @Rc int

 

SET @On=1

 

-- 이벤트와 이벤트 열을 확인한다.

IF @Events IS NULL or @Cols IS NULL BEGIN

    PRINT 'No Events or Coloumns.'

    RETURN -1

END

 

-- 파일경로와 파일명을 설정한다.

IF @TraceFileName IS NULL

SELECT @TraceFileName = 'C:\Trace\Trace' + CONVERT(CHAR(8),getdate(),112)

 

-- 추적 큐를 만든다

EXEC @Rc =sp_trace_create @TraceId OUT, @Options, @TraceFileName, @MaxFileSize, @StopTime

IF @Rc<>0 BEGIN

    PRINT 'Trace not started.'

    RETURN @Rc

END

PRINT 'Trace started.'

PRINT 'The trace file name is '+@TraceFileName+'.'

 

-- 추적할 이벤트 클래스들과 이벤트 열들을 지정한다

DECLARE @i int, @j int, @Event int, @Col int, @Colstring varchar(300)

 

IF RIGHT(@Events,1)<>',' SET @Events=@Events+','

SET @i=CHARINDEX(',',@Events)

WHILE @i<>0 BEGIN

    SET @Event=CAST(LEFT(@Events,@i-1) AS int)

    SET @Colstring=@Cols

    IF RIGHT(@Colstring,1)<>',' SET @Colstring=@Colstring+','

    SET @j=CHARINDEX(',',@Colstring)

    WHILE @j<>0 BEGIN

        SET @Col=CAST(LEFT(@Colstring,@j-1) AS int)

        EXEC sp_trace_setevent @TraceId, @Event, @Col, @On

        SET @Colstring=SUBSTRING(@Colstring,@j+1 ,300)

        SET @j=CHARINDEX(',',@Colstring)

    END

    SET @Events=SUBSTRING(@Events,@i+1,300)

    SET @i=CHARINDEX(',',@Events)

END

 

-- 필터를 설정한다

EXEC sp_trace_setfilter @TraceId, 10, 0, 7, N'SQL Profiler'

EXEC sp_trace_setfilter @TraceId, 1, 0, 7,  N'EXEC% sp_%trace%'

 

IF @IncludeFilter IS NOT NULL

    EXEC sp_trace_setfilter @TraceId, 1, 0, 6, @IncludeFilter

 

IF @ExcludeFilter IS NOT NULL

    EXEC sp_trace_setfilter @TraceId, 1, 0, 7, @ExcludeFilter

 

-- 추적을 활성화한다

EXEC sp_trace_setstatus @TraceId, 1

 

-- 추적을 기록한다. (테이블 사용)

IF OBJECT_ID('tempdb..TraceQueueList') IS NULL BEGIN

    CREATE TABLE tempdb..TraceQueueList (TraceID int, TraceName varchar(20), TraceFile sysname)

END

 

IF EXISTS(SELECT * FROM tempdb..TraceQueueList WHERE TraceName = @TraceName) BEGIN

    UPDATE tempdb..TraceQueueList

    SET TraceID = @TraceId, TraceFile = @TraceFileName

    WHERE TraceName = @TraceName

END

ELSE BEGIN

    INSERT tempdb..TraceQueueList

VALUES(@TraceId, @TraceName, @TraceFileName)

END

 

RETURN 0

GO

 

/* 실행하기 */

EXEC sp_trace_Start

GO

 

[참고]

?         output 파일을 지정하지 않으면, “C:\Trace” 폴더 밑에 추적 파일이 생성됩니다.

?         스크립트를 직접 실행하려면, “C:\Trace” 폴더를 미리 생성해야 합니다.

?         추적 파일이 커질 수도 있으므로, output 파일이 생성되는 곳의 공간을 충분히 확보합니다.

?         원하는 이벤트와 이벤트 열은 번호로 설정합니다. 이벤트와 이벤트 번호는 온라인 설명서를 참조하십시오.

반응형
반응형

실행 계획을 작성하는 작업은 CPU를 많이 사용하는 작업이기 때문에 새로운 실행 계획을 작성함으로써 얻어지는 이득이 실행 계획 작성에 드는 CPU 비용보다 크다면 재컴파일이 좋지만 그렇지 않은 불필요한 재컴파일은 가능한 한 제거하는 것이 좋습니다. 재컴파일이 발생하면 컴파일된 계획에 잠금을 걸기 때문에 동시성이 저하되므로 성능에 좋지 않은 영향을 미칠 수 있습니다.

실제로 운영 시스템을 모니터링하다 보면 사용자는 알지 못한 채 불필요한 재컴파일이 발생하는 경우가 흔히 있습니다. 그러므로 프로파일러 또는 추적 수집 SP를 사용하여 재컴파일에 대한 모니터링을 수행할 것을 권고합니다.

재컴파일을 모니터링하고자 하는 경우에는 EventSubClass 열을 수집해야 합니다.

다음은 EventSubClas 열의 값에 대한 설명입니다.

EventSubClass

설명

1

스키마 변경으로 인한 재컴파일

2

통계 변경으로 인한 재컴파일

3

지연된 컴파일로 인한 재컴파일

4

SET 옵션 변경으로 인한 재컴파일

5

임시 테이블 변경으로 인한 재컴파일

6

원격 행집합 변경으로 인한 재컴파일

7

FOR BROWSE 권한 변경으로 인한 재컴파일

8

쿼리 통지 환경 변경으로 인한 재컴파일

9

분할된 뷰 변경으로 인한 재컴파일

10

커서 옵션 변경으로 인한 재컴파일

11

OPTION (RECOMPILE) 요청으로 인한 재컴파일




참고로 재컴파일은 주로 다음과 같은 이유로 발생합니다.
- 변경된 행 임계값 (rowmodctr)
- DDL 문
- 스키마 변경
- 임시 테이블 사용
- SET 옵션 사용
   - ANSI_PADDING
   - FORCEPLAN
   - CONCAT_NULL_YIELDS_NULL
   - ANSI_WARNINGS
   - ANSI_NULLS
   - QUOTED_IDENTIFIER
   - ANSI_NULL_DFLT_ON
   - ANSI_NULL_DFLT_OFF

반응형
반응형
프로파일러를 이용하여 추적파일을 만든 경우
추적시에 테이블에 저장하면 서버에 부하가 가해지므로 테이블로 입력하도록 한다.

SELECT IDENTITY(int, 1, 1) AS RowNumber, * INTO [저장할 테이블명]
FROM fn_trace_gettable('C:\추적프로파일러.trc', default);

반응형
반응형

추적 데이터를 수집할 때의 권고 사항입니다.

 

?         불필요한 이벤트의 추가는 삼가합니다. 너무 많은 이벤트의 추가는 서버의 성능에 좋지 않은 영향을 있습니다.

?          일반적인 경우라면, 모든 이벤트 열을 포함시킵니다. 어떤 이벤트들은 보조적인 항목을 반환하는 어떤 항목들에 의존합니다.
적어도 다음 이벤트 열은 포함하는 것이 좋습니다.

-         BinaryData

-         ClientProcessID

-         CPU

-         Duration

-         EndTime

-         EventClass

-         EventSubClass

-         HostName

-         IntegerData

-         LoginName

-         NTUserName

-         Reads

-         SPID

-         StartTime

-         TextData

-         Writes

?         테이블에 추적을 직접 저장하는 것은 성능상 좋지 않습니다. 추적 파일을 생성한 , fn_trace_gettable 함수를 사용하면 테이블에 저장할 있습니다.

 

반응형
반응형

추적을 수집하는 목적에 따라 적절한 추적 이벤트와 이벤트 열의 설정이 필요합니다.

 

?         오래 실행되는 SQL 찾기

오래 실행되는 쿼리는 잘못 튜닝된 시스템, 잘못 작성된 응용 프로그램, 또는 단순히 많은 동작을 수행하는 작업등을 의미할 있습니다. 어떠한 경우건, 이러한 오래 실행되는 SQL 문을 찾아서 튜닝하는 것은 작업의 성능은 물론 전반적인 시스템 성능까지도 향상시킬 있습니다.

권장되는 추적 이벤트 : TSQL, SQL:BatchCompleted

정렬 기준 이벤트 : Duration

 

?         과도한 자원 사용자 찾기

과도한 자원을 사용하는 응용 프로그램이나 사용자를 찾는 추적은 DBA에게 유용한 도구가 있습니다. 이러한 추적 유형은 CPU I/O 자원 모두를 많이 사용하는 SQL 문을 살펴야 합니다. 프로세스나 사용자를 식별하여, 응용 프로그램을 튜닝할 있습니다.

권장되는 추적 이벤트 : TSQL, SQL:BatchCompleted

정렬 기준 이벤트 : CPU, Reads, Writes

 

?         교착 상태 알아내기

사용자의 작업에 따라 교착상태는 시스템에서 문제가 수도 있고 그렇지 않을 수도 있습니다. 많은 경우에 있어 교착 상태는 심각한 문제일 있는데, 경우 원인을 알아내는 것은 성능을 향상시키는데 핵심이 됩니다. 그러나 이러한 이벤트를 프로파일 하는 것은 자원을 많이 사용하게 되므로 주의해야 합니다.

- 권장되는 추적 이벤트

TSQL, SQL:BatchStarting 동작하는 SQL 일괄 처리(batch)

Locks, Lock:Deadlock 교착 상태 자체의 이벤트

Locks, Lock:Deadlock Chain 교착 상태에 이르는 이벤트 순서

            

?         캐시 관리 추적하기

다음과 같은 캐시 관리를 추적할 있습니다.

SP:CacheMiss (이벤트 ID 34)

SP:CacheInsert (이벤트 ID 35)

SP:CacheRemove (이벤트 ID 36)

SP:Recompile (이벤트 ID 37)

SP:CacheHit (이벤트 ID 38)

 

반응형
반응형

성능 문제의 디버깅은 문제의 원인을 알아내는 것으로 시작합니다. 많은 경우, 성능 문제는 비효율적인 SQL 문에서 기인합니다. 비효율적인 SQL 문이 문제의 원인이라고 의심될 , SQL Server 프로파일러를 사용하면 문제의 원인이 되는 SQL 문을 쉽게 찾을 있기 때문에, 성능 튜닝에 유용합니다.


SQL Server 프로파일러를 사용하는 단계입니다.

1.       다음 방법 하나를 이용하여 SQL Server 프로파일러 실행합니다.

[시작]->[프로그램]->[Microsoft SQL Server 2005]->[성능 도구]->[SQL Server Profiler] 또는 SQL Server Management Studio 상단 메뉴에서 [도구]->[SQL Server Profiler] 선택합니다.

2.       [파일]->[ 추적] 선택합니다.

3.       원하는 SQL 서버에 연결하면, [추적 속성]창이 나타납니다.

4.       추적이름을 입력합니다.

5.       템플릿을 사용할 경우에 템플릿을 선택합니다.

6.       파일에 저장하려면, [파일에 저장] 선택하고, 저장할 위치와 파일명을 입력합니다.

7.       최대 파일 크기 설정을 합니다.

8.       [이벤트] 탭을 선택한 , 추적을 원하는 이벤트와 이벤트 열을 추가하거나, 제거합니다. 많은 이벤트를 선택하는 것은 시스템에 상당한 부하를 일으킬 있으니, 추적을 원하는 이벤트만 선택하시기를 권고합니다.

9.       필터를 이용하고 싶다면, [ 필터] 버튼을 클릭하여, 원하는 필터를 정의합니다. 예를 들어, LoginName Test 것만 수집하고 싶다면 다음과 같이 설정합니다.

10.   [ 구성] 버튼을 클릭한 , 데이터 열의 순서를 조정합니다.

11.   [실행] 클릭하면, 수집이 시작됩니다.

12.   추적 정보 수집을 중지 하려면, 중지 버튼(붉은 네모) 클릭합니다.

반응형
반응형

수집된 성능 로그는 다음과 같이 확인할 수 있습니다.

1.       [시작] ->[설정] -> [제어판] -> [관리] -> [성능] 선택합니다.

2.       [로그 데이터 보기] 버튼을 클릭하면, [시스템모니터 등록 정보] 창이 나타납니다.

3.       로그 파일을 선택하고, 추가 버튼을 클릭하여, 원하는 파일을 추가합니다.

4.       [시간 범위] 클릭하여, 원하는 시간대를 조절합니다.

5.       데이터 탭을 클릭합니다.

6.       [추가] 클릭하여, 원하는 개체를 추가합니다.

7.       [확인] 클릭합니다.

반응형

+ Recent posts

반응형