로그 테이블이 너무 많아졌을 때 작업스케줄러에 해당 프로시저를 매일 일정시간에 한 번 돌리는 방법을 생각해볼 수 있다.

한 번 쿼리를 날릴 때 하루 치 데이터를 삭제한다고 가정하고,

삭제할 횟수와, 삭제하는 시간을 옵션으로 줄 수 있을 것이다.



INIT

-- 배치 테이블

IF OBJECT_ID('DBO.TCM_BATCH_LOG_MANAGE') IS NOT NULL

        DROP TABLE TCM_BATCH_LOG_MANAGE

 

CREATE TABLE TCM_BATCH_LOG_MANAGE

(

        SRC_TABLE NVARCHAR(200) NOT NULL

        , BASE_DEL_COL NVARCHAR(100) NOT NULL -- 데이터를 삭제할 때 사용할 날짜형식의 칼럼명

        , DEL_PERIOD INT NOT NULL -- 삭제기간

        , DEL_UNIT NVARCHAR(5) NOT NULL -- 삭제기간 단위 YEAR, MONTH

        , IS_TYPE_TC CHAR(1) NOT NULL -- T 타임, C 횟수

        , END_COND_CNT_SEC INT DEFAULT 0 NOT NULL-- N초 동안 또는 N, 하루치씩의 데이터를 계속해서 지운다

        , IS_MOVE_YN CHAR(1) NOT NULL -- 로그 데이터를 다른 테이블로 이동할건지

        , DEST_TABLE NVARCHAR(200) -- 어느테이블로 이동할 것인지

        , DEST_COL NVARCHAR(4000) -- 목적지 테이블에 INSERT COLUMNS

        , SELECT_COL NVARCHAR(4000) -- 로그 테이블에서 가져올 COLUMNS

        , IS_USE_YN CHAR(1) DEFAULT 'N'

        , LAST_RUNTIME DATETIME -- 마지막 실행시간

        , RUNTIME DECIMAL(10,3) -- 실행시간

        , RESULT NVARCHAR(5) -- 결과

        , AFFECTED_ROWS INT -- 영향받은 행 수

        , ERROR_MSG NVARCHAR(4000) -- 에러 메시지

)

GO

ALTER TABLE TCM_BATCH_LOG_MANAGE ADD CONSTRAINT CHK_SEC CHECK (END_COND_CNT_SEC > -1 )

ALTER TABLE TCM_BATCH_LOG_MANAGE ADD CONSTRAINT CHK_USE CHECK (IS_USE_YN IN ('Y', 'N'))

ALTER TABLE TCM_BATCH_LOG_MANAGE ADD CONSTRAINT CHK_TYPE CHECK (IS_TYPE_TC IN ('T', 'C'))

ALTER TABLE TCM_BATCH_LOG_MANAGE ADD CONSTRAINT CHK_MOVE CHECK (IS_MOVE_YN IN ('Y', 'N'))

ALTER TABLE TCM_BATCH_LOG_MANAGE ADD CONSTRAINT CHK_PERIOD CHECK (DEL_PERIOD < 0)

ALTER TABLE TCM_BATCH_LOG_MANAGE ADD CONSTRAINT CHK_UNIT CHECK (DEL_UNIT IN ('YEAR', 'MONTH'))

ALTER TABLE [DBO].[TCM_BATCH_LOG_MANAGE] ADD CONSTRAINT [PK_TCM_BATCH_LOG_MANAGE] PRIMARY KEY CLUSTERED

(

        [SRC_TABLE] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

GO

  

-- 데이터 이동 테스트

DROP TABLE LOG_TEST

CREATE TABLE LOG_TEST

(

        LOG_ID INT

        , ASSET_ID INT

)

 

--SAMPLE DATA INSERT

INSERT INTO TCM_BATCH_LOG_MANAGE(SRC_TABLE, BASE_DEL_COL, DEL_PERIOD, DEL_UNIT, IS_TYPE_TC, END_COND_CNT_SEC, IS_MOVE_YN, DEST_TABLE, DEST_COL, SELECT_COL, IS_USE_YN)

VALUES

('TAS_ASSET_HISTORY', 'CREATE_DATE', -1, 'YEAR', 'C', 2 , 'Y', 'LOG_TEST', 'LOG_ID, ASSET_ID', 'LOG_ID, ASSET_ID', 'Y')

 


SP

CREATE PROCEDURE BATCH_LOG_MANAGE

AS

BEGIN

 

        DECLARE @SRC_TABLE NVARCHAR(200), @BASE_DEL_COL NVARCHAR(100), @DEL_PERIOD INT, @DEL_UNIT NVARCHAR(5);

        DECLARE @IS_TYPE_TC CHAR(1), @IS_MOVE_YN CHAR(1)

        DECLARE @END_COND INT, @CUR_END_SECOND DATETIME, @CUR_COUNT INT; -- END_CONDITION_MINUTE DATEADD 로 계산하여 넣어둠

        DECLARE @DEST_TABLE NVARCHAR(200), @DEST_COL NVARCHAR(4000), @SELECT_COL NVARCHAR(4000), @IS_DEST_TABLE NVARCHAR(200)

 

        -- 지울 때는 하루치씩 지운다

        DECLARE @DEL_DATE DATETIME  -- 삭제할 날짜

        DECLARE @SQL NVARCHAR(4000)

        DECLARE @PARAMS NVARCHAR(4000)

        DECLARE @AFFECTED_ROWS INT

 

        -- 루프 변수

        DECLARE @I INT, @MAX_I INT      

        DECLARE @DEL_FLAG BIT

        DECLARE @STIME DATETIME

       

        if OBJECT_ID('TEMPDB..#TMP_MANAGER') is not null

               DROP TABLE #TMP_MANAGER

 

        SELECT ROW_NUMBER() OVER(ORDER BY SRC_TABLE) AS ID, *

        INTO #TMP_MANAGER

        FROM TCM_BATCH_LOG_MANAGE

        WHERE IS_USE_YN = 'Y'

 

        SELECT @I = 1, @MAX_I = MAX(ID) FROM #TMP_MANAGER

 

        WHILE @I <= @MAX_I

        BEGIN

               SELECT @SRC_TABLE = SRC_TABLE, @BASE_DEL_COL = BASE_DEL_COL, @DEL_PERIOD = DEL_PERIOD, @DEL_UNIT = DEL_UNIT, @IS_TYPE_TC = IS_TYPE_TC,

                       @END_COND = END_COND_CNT_SEC, @IS_MOVE_YN = IS_MOVE_YN,

                       @DEST_TABLE = DEST_TABLE, @DEST_COL = DEST_COL, @SELECT_COL = SELECT_COL,

                       -- 아래 삭제용 WHILE문 용 변수 초기화

                       @DEL_FLAG = 1, @CUR_COUNT = 0, @CUR_END_SECOND = DATEADD(SS, END_COND_CNT_SEC, GETDATE()), @AFFECTED_ROWS = 0, @STIME = GETDATE()

               FROM #TMP_MANAGER

               WHERE ID = @I

 

               --마지막 실행시간

               UPDATE TCM_BATCH_LOG_MANAGE SET LAST_RUNTIME = GETDATE(), RUNTIME = NULL, RESULT = NULL, AFFECTED_ROWS = 0, ERROR_MSG = NULL WHERE SRC_TABLE = @SRC_TABLE

 

               -- 실제 지우는 WHILE

               WHILE 1 = 1

               BEGIN

                       BEGIN TRY

                              SET @SQL = 'SELECT @DEL_DATE = CAST(DATEADD(DD, 1, MIN(' + @BASE_DEL_COL + ')) AS DATE) FROM ' + @SRC_TABLE

                                                      + ' WHERE ' + @BASE_DEL_COL + ' < DATEADD(' + @DEL_UNIT + ', ' + CONVERT(NVARCHAR(10), @DEL_PERIOD) + ', GETDATE())';

                              SET @PARAMS = '@DEL_DATE DATETIME OUTPUT'

                              EXEC SP_EXECUTESQL @SQL, @PARAMS, @DEL_DATE OUTPUT;

              

                              IF(@DEL_DATE IS NULL)

                              BEGIN

                                      BREAK

                              END

 

                              IF @IS_MOVE_YN = 'Y'

                              BEGIN

                                      -- 목적지 테이블 검색

                                      SET @SQL = 'SELECT @IS_DEST_TABLE = TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ''DBO'' AND  TABLE_NAME = @DEST_TABLE'

                                      SET @PARAMS = '@DEST_TABLE NVARCHAR(200), @IS_DEST_TABLE NVARCHAR(200) OUTPUT'

                                      EXEC SP_EXECUTESQL @SQL, @PARAMS, @DEST_TABLE, @IS_DEST_TABLE OUTPUT;

 

                                      IF @IS_DEST_TABLE IS NULL

                                      BEGIN

                                              UPDATE TCM_BATCH_LOG_MANAGE SET ERROR_MSG = '복사할 목적지 테이블이 없습니다' WHERE SRC_TABLE = @SRC_TABLE

                                              SET @DEL_FLAG = 0

                                              BREAK

                                      END

 

                                      -- 데이터 복사

                                      SET @SQL = 'INSERT INTO ' + @DEST_TABLE + '('+ @DEST_COL + ') SELECT ' + @SELECT_COL + ' FROM ' + @SRC_TABLE + ' WHERE ' + @BASE_DEL_COL + ' < @DEL_DATE'

                                      SET @PARAMS = '@DEL_DATE DATETIME'

                                      EXEC SP_EXECUTESQL @SQL, @PARAMS, @DEL_DATE;

                              END

 

                              SET @SQL = 'DELETE FROM ' + @SRC_TABLE + ' WHERE ' + @BASE_DEL_COL + ' < @DEL_DATE'

                              SET @PARAMS = '@DEL_DATE DATETIME'

                              EXEC SP_EXECUTESQL @SQL, @PARAMS, @DEL_DATE;

 

                              --영향받은 행수

                              SET @AFFECTED_ROWS += @@ROWCOUNT

                       END TRY

                       BEGIN CATCH

                              UPDATE TCM_BATCH_LOG_MANAGE SET ERROR_MSG = ERROR_MESSAGE() WHERE SRC_TABLE = @SRC_TABLE

                              SET @DEL_FLAG = 0

                              BREAK

                       END CATCH

 

                       SET @CUR_COUNT += 1

                       IF @IS_TYPE_TC = 'T' AND GETDATE() >= @CUR_END_SECOND

                              BREAK

                       ELSE IF @IS_TYPE_TC = 'C' AND @CUR_COUNT >= @END_COND

                              BREAK

               END

              

               UPDATE TCM_BATCH_LOG_MANAGE SET RESULT = (CASE WHEN @DEL_FLAG = 1 THEN '성공' ELSE '실패' END), AFFECTED_ROWS = @AFFECTED_ROWS

                       , RUNTIME = DATEDIFF(MILLISECOND, @STIME, GETDATE()) /  CONVERT(FLOAT,1000)

               WHERE SRC_TABLE = @SRC_TABLE

 

               SET @I += 1

        END

 

        DROP TABLE #TMP_MANAGER

END

 

 


Posted by motolies
,