SQL Server : 변경 사항 추적을 도입하는 오버 헤드를 조사했습니다.

12362 단어 SQLServerDB검증

배경



여기 문서에서 변경 내용 추적을 확인했지만 오버헤드에 대해 자세히 살펴보고 결과를 공유합니다.

조사 방법



설문조사


use [master]
GO
CREATE DATABASE [TESTDB]
GO

-- DB レベルで変更の追跡を有効化
ALTER DATABASE [TESTDB] SET CHANGE_TRACKING = ON
GO

USE [TESTDB]
-- ①変更の追跡を有効化するテーブルを作成
CREATE TABLE ChangeTrackingTBL(
    C1 int identity primary key,
    C2 int,
    C3 varchar(36),
    C4 datetime2(0) DEFAULT (GETDATE())
)
CREATE INDEX  NCIX_ChangeTrackingTBL ON ChangeTrackingTBL (C2)

-- 変更の追跡の有効化 (テーブルレベル)
ALTER TABLE ChangeTrackingTBL ENABLE CHANGE_TRACKING

-- ②変更の追跡を有効化しないテーブルを作成
CREATE TABLE NOTrackingTBL(
    C1 int identity primary key,
    C2 int,
    C3 varchar(36),
    C4 datetime2(0) DEFAULT (GETDATE())
)
CREATE INDEX  NCIX_NOTrackingTBL ON NOTrackingTBL (C2)

-- ③変更の追跡を有効化せず、インデックスを一つ多くもつテーブルを作成
CREATE TABLE IDX_NoTrackingTBL(
    C1 int identity primary key,
    C2 int,
    C3 varchar(36),
    C4 datetime2(0) DEFAULT (GETDATE())
)
CREATE INDEX  NCIX_IDX_NoTrackingTBL ON IDX_NoTrackingTBL (C2)
CREATE INDEX  NCIX_IDX_NoTrackingTBL2 ON IDX_NoTrackingTBL (C3)

테스트용 DB를 작성하고 작성한 DB에서 변경사항 추적을 활성화합니다.
다음으로 3 패턴의 테이블을 만듭니다.
① 변경 추적을 활성화하는 테이블 만들기
② 변경 추적을 활성화하지 않는 테이블을 작성
③변경 추적을 활성화하지 않고 인덱스를 하나 더 가진 테이블을 작성

로드하는 쿼리 실행



각 테이블에 대해 1행 단위의 INSERT, UPDATE, DELETE를 각각 1만회 실행했습니다.

평가 쿼리



캐시에서 해당 쿼리의 실행 시간을 확인하여 각 테이블의 업데이트 처리 성능을 평가합니다.
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT TOP 100
  DB_NAME(qt.dbid) as database_name
  --query text
  ,qt.TEXT as parent_query
  ,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 statement
  -- average
  ,total_worker_time / qs.execution_count / 1000 as average_CPU_time_ms
  ,total_elapsed_time / qs.execution_count / 1000 as average_duration_ms
  ,total_physical_reads / qs.execution_count / 1000 as average_physical_reads
  -- execution count
  ,qs.execution_count as execution_count
  -- creation / execution time
  ,last_execution_time
  ,creation_time
  -- total
  ,total_worker_time / 1000 as total_CPU_time_ms
  ,total_elapsed_time / 1000 as total_duration_ms
  ,total_physical_reads / 1000 as total_physical_reads
  -- query plan
  ,qp.query_plan  -- プランもみたいときはコメント外す
  ,qs.plan_handle
FROM sys.dm_exec_query_stats qs
OUTER APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt -- クエリテキスト用
OUTER apply sys.dm_exec_query_plan(plan_handle) as qp -- プランプラン用
WHERE
   qt.TEXT like '%TrackingTBL%'
order by execution_count desc
option (recompile)

여기서 "dm_exec_query_stast의 실행 시간에 변경 추적 테이블에 INSERT 시간의 시간이 걸릴 것인가"에 대해서는 확인이 필요했기 때문에 실행 계획을 체크했습니다.

실행 계획을 보면 변경 추적 테이블에 대한 INSERT도 포함되어 있음을 알 수 있습니다.
따라서, 이 방법으로 평가한 결과는 타당하다고 말할 수 있을 것 같습니다.

조사 결과



정확한 시간을 공개하는 것은 금지되어 있었기 때문에 비율로 공개하고 싶습니다.



변경사항 추적 없음
변경사항 추적 있음
변경 추적 없음/추가 인덱스 하나 생성


INSERT CPU 시간
1
1.33
1.30

UPDATE CPU 시간
1
2.02
34.2

DELETE CPU 시간
1
0.84
0.97




변경사항 추적 없음
변경사항 추적 있음
변경 추적 없음/추가 인덱스 하나 생성


INSERT 실행 시간
1
1.33
1.29

UPDATE 실행 시간
1
2.02
34.2

DELETE 실행 시간
1
0.85
0.97


이상의 결과로부터, 이하의 것을 알았습니다.
  • INSERT에 대해서는 인덱스를 1 개 작성하는 것만큼의 부하라고 하는 인식으로 좋을 것
  • UPDATE에 대해서는 인덱스를 1개 작성하는 것보다는 오버헤드가 적고, 변경의 추적을 넣지 않는 것보다는 많다, 라고 하는 중간 정도의 부하라고의 인식으로 OK
  • 이번 검증에서 인덱스 추가로 UPDATE 비용이 비약적으로 상승했습니다

  • DELETE의 처리는 아무도 변하지 않는 것 같다
  • 변경 추적이 더 적은 부하를 갖는 값이 되었지만 그럴 수는 없으므로 오류로 간주됩니다


  • 요약



    변경 추적을 도입하는 오버헤드는 도입하지 않은 상태에 비해 커지지만 인덱스를 하나 추가하는 것의 영향보다 작다고 결론 내렸습니다.

    ※기타 오버헤드



    정기적으로 변경 추적을 정리하는 작업 부하가 발생합니다.
    다만, last page insert 하고 있을 것이므로, 변경의 추적 테이블에의 INSERT와, 만료된 데이터를 변경의 추적 테이블로부터 삭제하는 처리와의 블로킹은 발생하지 않을 것이라고 생각하고 있습니다.

    좋은 웹페이지 즐겨찾기