데이터엔지니어 군고구마
  • DB에 저장한 Perfmon 데이터 관리
    2015년 11월 11일 18시 49분 02초에 업로드 된 글입니다.
    작성자: DE 군고구마
    반응형

    DB서버에 perfmon을 저장하는 방법을 이전 포스트에서 포스팅 했습니다.

    http://burning-dba.tistory.com/43


    하지만 perfmon의 row 수가 많아지면, 성능 이슈 및 용량의 이슈가 발생합니다. 현재 1분에 1건씩 perfmon을 수집하여, 데이터를 넣고 있는데 한달정도 운영하였는데 건수가 벌써 150만건을 넘었습니다. 이렇게 많은 건수가 차후에 쌓이고 쌓여, 성능 이슈가 발생하거나 용량이 문제가 생길 수 있습니다. 

    그래서 이번 포스트에서는 지난 번의 내용에서 응용을 하여, 5개씩 (5분) 1 set로 지정하여, 데이터를 1/5로 줄여, 데이터를 old 테이블에 

    저장하는 방법에 대해서 적어보고자 합니다.


    요구 사항은 다음과 같습니다.


    ① 기존의 데이터를 보존한다.

    ② 데이터의 사이즈를 줄인다. (row의 수를 줄인다.)

    ③ 현재 1분 단위로 perfmon을 수집하는데, 5분(5개 1set 로 묶어서 평균을 낸다.) 단위로 데이터 가공하여, 저장한다.


    우선 1차적으로 데이터를 가공합니다. 

    		select  [CounterID]
    				,[CounterDateTime]
    				,[CounterValue]
    				,case  when SUBSTRING(counterdatetime,16,1) in (0,1,2,3,4) then 'A' 
    						when SUBSTRING(counterdatetime,16,1) in (5,6,7,8,9) then 'B'  end as 'type'
    				,convert(char(15),counterdatetime) as 'mtime'
    		from [dbo].[CounterData_test] with(nolock)
    


    이 가공되는 데이터는 다음과 같은 원리로 이루어집니다.


    ① mtime으로 데이터를 10분 단위 묶을 수 있도록, convert를 이용하여, 분의 앞자리 까지 짜릅니다.

    ② 잘려진 mtime 만으로, 5분을 알수 없으므로, SUBSTRING을 이용하여, 분의 뒷자리의 데이터를 case를 이용하여, type을 나눕니다.


    위 처럼 가공된 데이터를 CTE를 이용하여, 다시 group 를 거쳐 가공합니다. 한번에 5분 단위로 쪼개기 어려워서 CTE를 이용하여, 다시 한번 데이터를 가공 하였습니다.

     

    with perfmon_CTE (counterid,[CounterDateTime],[CounterValue],type,mtime)
    as 
    		(	
    		select  [CounterID]
    				,[CounterDateTime]
    				,[CounterValue]
    				,case  when SUBSTRING(counterdatetime,16,1) in (0,1,2,3,4) then 'A' 
    						when SUBSTRING(counterdatetime,16,1) in (5,6,7,8,9) then 'B'  end as 'type'
    				,convert(char(15),counterdatetime) as 'mtime'
    		from [dbo].[CounterData_test] with(nolock)
    		)
    select  max([CounterDateTime]) as  'Date'
    		,counterid
    		,convert(float,avg(CounterValue)) as '5 minute Avg'
    		,mtime
    		,type
    from perfmon_CTE
    group by counterid,mtime,type
    order by  'Date' asc
    go
    


    위처럼 가공하면, 다음과 같은 결과물을 얻을 수 있습니다.


    컬럼의 대한 설명은 다음과 같습니다.


    ① Date         : 이 컬럼은 차후에 old 테이블을 조회 할때 사용하기 위해서 counterid와 함께 복합 인덱스로 PK를 잡았습니다.

    ② counterid    : counter의 항목 번호 입니다. 이 부분은 기존의 CounterData 테이블과 동일한 의미입니다.

    ③ 5 minute Avg : 5개 1set의 평균값 입니다.

    ④ mtime       : 10분 단위까지의 분의 앞자리 값 입니다. (group by를 위하여 사용)

    ⑤ type         : A type (0,1,2,3,4) B type (5,6,7,8,9) 입니다. 결국 숫자는 분의 뒷자리를 나타냅니다. 5분 단위로 쪼개기 위한 구분자 입니다.


    이제 데이터를 넣을 old 테이블을 만들어 줍니다.


    create table [dbo].[CounterData_old]
    (
     date					datetime	not null
    ,counterid			int			not null
    ,five_minute_Avg		float		not null
    ,m_time				char(15)	not null
    ,type					char(1)	not null
    constraint PK_CounterData_old_1 primary key clustered(counterid,date)
    )
    go
    
    create nonclustered index NC_CounterData_old_2	on [CounterData_old] (date)
    go
    

    old 테이블은 차후에 old 테이블을 검색을 위한 인덱스와 데이터를 효율적으로 관리하기 위해서 컬럼 및 인덱스를 추가하였습니다.

    만들어진 old 테이블에 아까의 스크립트에 insert 구문을 추가하여, 데이터를 밀어 넣습니다. 해당 작업은 운영서버에서는 이슈가 있을 수 있으므로, 조심해야 합니다.



    with perfmon_CTE (counterid,[CounterDateTime],[CounterValue],type,mtime)
    as 
    		(	
    		select  top 1000 [CounterID]
    				,[CounterDateTime]
    				,[CounterValue]
    				,case  when SUBSTRING(counterdatetime,16,1) in (0,1,2,3,4) then 'A' 
    						when SUBSTRING(counterdatetime,16,1) in (5,6,7,8,9) then 'B'  end as 'type'
    				,convert(char(15),counterdatetime) as 'mtime'
    		from [dbo].[CounterData_test] with(nolock)
    		)
    insert into [dbo].[CounterData_old] 
    select  max([CounterDateTime]) as  'Date'
    		,counterid
    		,convert(float,avg(CounterValue)) as '5 minute Avg'
    		,mtime
    		,type
    from perfmon_CTE
    group by counterid,mtime,type
    order by counterid, 'Date' asc
    go

    테이블이 초기에 1,547,544 건에서 309,570건으로 줄었습니다. 이는 몇몇의 데이터가 5분 단위가 안되기 때문에 row의 차이가 날 수 있습니다. 


    해당 작업을 실행 후에 기존의 데이터를 보관 주기 정책을 수립하여, 몇개월 단위로 JOB 스케줄러를 걸고, 자동으로 삭제되도록 하면, 관리가 수월 할 것으로 보여집니다.

    하지만, 주의해야 할 점은 delete 시에 너무 많은 건수를 한번에 지울 경우 CounterData 테이블에 문제가 있을 수 있으니 주의하여, 지워야 합니다.

    실제로 3천만건에 육박하는 데이터를 지울 때 10일 단위 또는 30일 단위로 지우도록 while 문을 만들어서 수행하였습니다. 


    운영DB의 경우 지속적으로 perfmon이 데이터를 수집하고 있기에 delete 발생하는 lock에 대한 이슈를 고민해야 합니다. 



    감사합니다.


    반응형

    'Database > MSSQL Server' 카테고리의 다른 글

    Parameter Sniffing Trouble Shooting  (0) 2015.11.18
    Parameter Sniffing에 관하여...  (0) 2015.11.17
    xp_delete_file  (0) 2015.11.10
    IN-Memory OLPT (MSSQL 2014)  (0) 2015.10.28
    SELECT 에 의한 DeadLock 발생  (1) 2015.10.28
    댓글