임시 테이블 사용 시나리오 | Microsoft Docs 
 임시 테이블 사용 시나리오 Temporal Table Usage Scenarios 
 임시 테이블 은 일반 적 으로 데이터 변경 기록 을 추적 하 는 데 필요 한 시나리오 에서 유용 합니다 . Temporal Tables are generally useful in scenarios that require tracking history of data changes . 
 생산 성 이 상당히 높 으므로 다음 사용 사례 에서 임시 테이블 을 사용 을 고려 하 는 것 이 좋 습니다 . We recommend you to consider Temporal Tables in the following use cases for major productivity benefits . 
 데이터 감사 Data Audit 
 변경 된 사항 및 시기 를 추적 하 고 지정 시간 에 법정 분석 을 수행 하 는 데 필요 한 중요 정보 가 저장 된 테이블 에서 는 임시 시스템 버전 관리 를 사용 합니다 . Use temporal system - versioning on tables that store critical information for which you need to keep track of what has changed and when , and to perform data forensics at any point in time . 
 임시 시스템 버전 관리 테이블 을 사용 하 면 개발 주기 의 초기 단계 에서 데이터 감사 시나리오 에 대해 계획 하 고 필요 할 때 기존 응용 프로그램 이나 솔루션 에 데이터 감사 를 추가 할 수 있 습니다 . Temporal system - versioned tables allows you to plan for data audit scenarios in the early stages of the development cycle or to add data auditing to existing applications or solutions when you need it . 
 다음 다이어그램 에서 는 현재 ( 파란색 으로 표시 ) 및 기록 행 버전 ( 회색 으로 표시 ) 을 포함 한 데이터 샘플 을 사용 하 여 Employee 테이블 시나리오 를 보여 줍니다 . The following diagram shows an Employee table scenario with the data sample including current ( marked with blue color ) and historical row versions ( marked with grey color ) . 
 다이어그램 의 오른쪽 부분 에서 는 시간 축 에 행 버전 을 시각 화 하 고 , SYSTEM _ TIME 절 을 포함 하 거나 포함 하 지 않 은 temporal 테이블 의 여러 쿼리 형식 으로 선택 하 는 행 을 시각 화 합니다 . The right - hand portion of the diagram visualizes row versions on time axis and what are the rows you select with different types of querying on temporal table with or without SYSTEM _ TIME clause . 
 데이터 감사 를 위해 새 테이블 에 시스템 버전 관리 를 사용 하 도록 설정 Enabling system - versioning on a new table for data audit 
 데이터 감사 가 필요 한 정보 를 파악 하 고 나 면 임시 시스템 버전 이 관리 되 는 데이터베이스 테이블 을 만듭니다 . If you have identified information that needs data audit , create database tables as temporal system - versioned . 다음 의 간단 한 예제 에서 는 가상 HR 데이터베이스 에서 직원 정보 를 사용 하 는 시나리오 를 보여 줍니다 . The following simple example illustrates a scenario with Employee information in hypothetical HR database : 
 시스템 에서 버전 이 관리 되 는 임시 테이블 을 만드 는 다양 한 옵션 은 시스템 버전 임시 테이블 만들 기 에 설명 되 어 있 습니다 . Various options to create temporal system - versioned table are described in Creating a System - Versioned Temporal Table . 
 데이터 감사 를 위해 기존 테이블 에 시스템 버전 관리 를 사용 하 도록 설정 Enabling system - versioning on an existing table for data audit 
 기존 데이터베이스 에서 데이터 감사 를 수행 해야 할 경우 시스템 버전 이 관리 되 도록 ALTER TABLE 을 사용 하 여 비 temporal 테이블 을 확장 합니다 . If you need to perform data audit in existing databases , use ALTER TABLE to extend non - temporal tables to become system - versioned . 비 임시 테이블 을 시스템 버전 임시 테이블 로 변경 에 설명 된 대로 응용 프로그램 에서 새로운 변경 이 발생 하 지 않 도록 HIDDEN 으로 기간 열 을 추가 합니다 . In order to avoid breaking changes in your application , add period columns as HIDDEN , as explained in Alter Non - Temporal Table to be System - Versioned Temporal Table . 다음 예제 에서 는 가상 HR 데이터베이스 에 있 는 기존 직원 테이블 에서 시스템 버전 관리 를 사용 하 도록 설정 하 는 방법 을 보여 줍니다 . The following example illustrates enabling system - versioning on an existing Employee table in a hypothetical HR database : 
 Turn ON system versioning in Employee table in two steps 
 ( 1 ) add new period columns ( HIDDEN ) 
 ( 2 ) create default history table 
 ValidFrom datetime 2 ( 2 ) GENERATED ALWAYS AS ROW START HIDDEN 
 constraint DF _ ValidFrom DEFAULT DATEADD ( second , - 1 , SYSUTCDATETIME ( ) ) 
 constraint DF _ ValidTo DEFAULT ' 9999 . 12 . 31 23 : 59 : 59 . 99 ' 
 위 의 스크립트 를 실행 하 고 나 면 모든 데이터 변경 사항 이 기록 테이블 에 투명 하 게 수집 됩니다 . After executing the above script , all data changes will be collected transparently in the history table . 
 일반 적 인 데이터 감사 시나리오 에서 는 관심 있 는 기간 에 개별 행 에 적용 된 모든 데이터 변경 에 대해 쿼리 합니다 . In typical data audit scenario , you would query for all data changes that were applied to an individual row within a period of time of interest . 이 사용 사례 를 효율 적 으로 보여 줄 수 있 도록 기본 기록 테이블 은 클러스터 형 행 - 저 장소 B - 트리 로 만들 어 집니다 . The default history table is created with clustered row - store B - Tree to efficiently address this use case . 
 데이터 분석 수행 Performing data analysis 
 FOR SYSTEM _ TIME BETWEEN . .. AND 를 FOR SYSTEM _ TIME ALL 로 바꿔 특정 직원 에 대한 데이터 변경 의 전체 기록 을 분석 합니다 . Replace FOR SYSTEM _ TIME BETWEEN . .. AND with FOR SYSTEM _ TIME ALL to analyze the entire history of data changes for that particular employee : 
 FOR SYSTEM _ TIME ALL WHERE 
 범위 를 벗어나 지 않 고 기간 내 에서 만 활성 상태 인 행 버전 을 검색 하 려면 CONTAINED IN 을 사용 합니다 . To search for row versions that were active only within a period ( and not outside of it ) , use CONTAINED IN . 이 쿼리 는 기록 테이블 만 쿼리 하 므로 매우 효율 적 입니다 . This query is very efficient because it only queries the history table : 
 CONTAINED IN ( ' 2014 - 01 - 01 00 : 00 : 00 . 0000000 ', ' 2015 - 01 - 01 00 : 00 : 00 . 0000000 ') 
 마지막 으로 일부 감사 시나리오 에서 는 과거 의 지정 시간 의 전체 테이블 모습 을 볼 수 도 있 습니다 . Finally , in some audit scenarios , you may want to see how entire table looked like at any point in time in the past : 
 시스템 버전 관리 temporal 테이블 에서 는 UTC 표준 시간대 의 기간 열 에 대한 값 이 저장 됩니다 . 하지만 데이터 를 필터링 하고 결과 를 표시 하 기 위해서 는 현지 표준 시간대 를 사용 하 여 작업 하 는 것 이 항상 좀 더 편리 합니다 . System - versioned temporal tables store values for period columns in UTC time zone , while it is always more convenient to work with local time zone both for filtering data and displaying results . 다음 코드 예제 에서 는 SQL Server 2016 에 도입 된 AT TIME ZONE 을 사용 하 여 원래 현지 표준 시간 대 에 지정 되 었 다가 UTC 로 변환 된 필터링 조건 을 적용 하 는 방법 에 대해 보여 줍니다 . The following code example shows how to apply filtering condition that is originally specified in the local time zone and then converted to UTC using AT TIME ZONE introduced in SQL Server 2016 : 
 /* Add offset of the local time zone to current time */ 
 / * Convert AS OF filter to UTC */ 
 , [ Address ] 
 , [ AnnualSalary ] 
 , ValidFrom AT TIME ZONE ' Pacific Standard Time ' AS ValidFromPT 
 , ValidTo AT TIME ZONE ' Pacific Standard Time ' AS ValidToPT 
 AT TIME ZONE 을 사용 하 는 것 은 시스템 버전 관리 된 테이블 이 사용 되 는 다른 모든 시나리오 에 도움 이 됩니다 . Using AT TIME ZONE is helpful in all other scenarios where system - versioned tables are used . 
 FOR SYSTEM _ TIME 이 포함 된 임시 절 에 지정 된 필터링 조건 은 SARG 가능 합니다 . Filtering conditions specified in temporal clauses with FOR SYSTEM _ TIME are SARG - able ( i . e 예 를 들 어 SQL Server 는 기본 클러스터 행 인덱스 를 활용 하 여 검색 ( scan ) 작업 대신 찾 기 ( seek ) 를 수행 할 수 있 습니다 . SQL Server can utilize underlying clustered index to perform a seek instead of a scan operation . 
 AT TIME ZONE 을 기간 열 에 적용 하 면 SQL Server 에서 는 테이블 / 인덱스 검색 을 수행 하 지만 이 작업 은 비용 이 매우 많이 들 수 있 습니다 . If you apply AT TIME ZONE to period columns , SQL Server will perform a table / index scan , which can be very expensive . 쿼리 에서 Avoid this type of condition in your queries : 
 참고 항목 : 시스템 버전 임시 테이블 의 데이터 쿼리 See also : Querying Data in a System - Versioned Temporal Table . 
 지정 시간 분석 ( 시간 이동 ) Point in Time Analysis ( Time Travel ) 
 일반 적 으로 개별 레코드 에 발생 한 변경 에 중점 을 두 는 데이터 감사 와 는 달리 시간 이동 시나리오 에서 사용 자 는 시간 의 흐름 에 따라 전체 데이터 집합 이 변경 된 방식 을 확인 할 수 있 습니다 . Unlike data audit , where the focus is typically on changes that occurred to an individual records , in time travel scenarios users want to see how entire data sets changed over time . 경우 에 따라 시간 이동 에 는 관련 temporal 테이블 이 여러 개 포함 되 어 있 으며 각 테이블 은 개별 적 으로 변경 됩니다 . 이 테이블 에서 다음 을 분석 할 수 있 습니다 . Sometimes time travel includes several related temporal tables , each changing at independent pace , for which you want to analyze : 
 기록 및 현재 데이터 의 중요 한 지표 에 대한 추세 Trends for the important indicators in the historical and current data 
 과거 의 지정 시간 " 을 기준 으로 " 전체 데이터 의 정확 한 스냅숏 ( 어제 , 한 달 전 등 ) Exact snapshot of the entire data “ as of ” any point in time in the past ( yesterday , a month ago , etc . ) 
 관심 있 는 두 지정 시간 간 의 차이 ( 예 : 한 달 전 vs . 3 개월 전 ) Differences in between two point in time of interest ( a month ago vs . three months ago , for instance ) 
 실제로 시간 이동 분석 이 필요 한 시나리오 는 많 습니다 . There are many real - world scenarios which require time travel analysis . 이 사용 시나리오 를 보여 줄 수 있 도록 자동 생성 기록 을 사용 하 는 OLTP 에 대해 살펴보 겠 습니다 . To illustrate this usage scenario , let ' s look at OLTP with auto - generated history . 
 자동 생성 된 데이터 기록 을 사용 하 는 OLTPOLTP with Auto - Generated Data History 
 트랜잭션 처리 시스템 에서 는 일반 적 으로 시간 의 흐름 에 따라 중요 한 메트 릭 이 변경 되 는 방식 을 분석 합니다 . In transaction processing systems , it is not unusual to analyze how important metrics change over time . 이상 적 으로 는 데이터 의 최신 상태 에 액세스 할 때 대기 시간 과 데이터 잠금 이 최소한 으로 발생 되 어야 하 므로 OLTP 응용 프로그램 에서 는 기록 분석 으로 인해 성능 이 저하 되 면 안 됩니다 . Ideally , analyzing history should not compromise performance of the OLTP application where access to the latest state of data must occur with minimal latency and data locking . 시스템 버전 관리 된 temporal 테이블 은 사용 자 가 전체 변경 내역 을 나중 에 분석 할 수 있 도록 현재 데이터 와 는 별도 로 투명 하 게 유지 하 여 주 OLTP 작업 에 영향 이 최소한 으로 미칠 수 있 도록 디자인 되 었 습니다 . System - versioned temporal tables are designed to allow users to transparently keep the full history of changes for later analysis , separately from the current data , with the minimal impact on the main OLTP workload . 
 부하 가 높 은 트랜잭션 처리 작업 을 위해서 는 메모리 액세스 에 최적 화 된 테이블 을 포함 한 시스템 버전 임시 테이블 을 사용 하 는 것 이 좋 습니다 . 이렇게 하 면 현재 메모리 내 데이터 와 디스크 의 전체 변경 기록 을 비용 효율 적 인 방식 으로 저장 할 수 있 습니다 . For high transactional processing workloads , we recommend that you use System - Versioned Temporal Tables with Memory - Optimized Tables , which allow you to store current data in - memory and full history of changes on disk in a cost effective way . 
 기록 테이블 의 경우 다음 과 같 은 이유 로 클러스터 형 columnstore 인덱스 를 사용 하 는 것 이 좋 습니다 . For the history table , we recommend that you use a clustered columnstore index for the following reasons : 
 일반 적 인 추세 분석 에서 는 클러스터 형 columnstore 인덱스 에서 제공 하 는 쿼리 성능 을 활용 합니다 . Typical trend analysis benefits from query performance provided by a clustered columnstore index . 
 메모리 최적화 테이블 이 있 는 데이터 플러시 작업 은 기록 테이블 에 클러스터 형 columnstore 인덱스 가 있 을 때 부하 가 높 은 OLTP 작업 에서 도 최고 의 성능 을 보여 줍니다 . The data flush task with memory - optimized tables performs best under heavy OLTP workload when the history table has a clustered columnstore index . 
 클러스터 형 columnstore 인덱스 는 일부 열 이 동시 에 변경 되 지 않 는 시나리오 에서 특히 뛰어난 압축 기능 을 제공 합니다 . A clustered columnstore index provides excellent compression , especially in scenarios where not all columns are changed at the same time . 
 메모리 내 OLTP 에 temporal 테이블 을 사용 하 면 메모리 내 전체 데이터 집합 을 유지 해야 하 는 부담 을 덜 고 핫 데이터 와 콜드 데이터 를 쉽 게 구분 할 수 있 게 됩니다 . Using temporal tables with in - memory OLTP reduces the need to keep the entire data set in - memory and enables you to easily distinguish between hot and cold data . 
 이 범주 에 잘 맞 는 실제 시나리오 의 예 로 인벤토리 관리 또는 환율 거래 등 이 있 습니다 . Examples of the real - world scenarios that fit well into this category are inventory management or currency trading , among others . 
 다음 다이어그램 은 인벤토리 관리 에 사용 되 는 간단 한 데이터 모델 을 보여 줍니다 . The following diagram shows simplified data model used for inventory management : 
 다음 코드 예제 에서 는 기록 테이블 에서 클러스터 형 columnstore 인덱스 가 포함 된 메모리 내 시스템 버전 관리 된 temporal 테이블 로 ProductInventory 를 만듭니다 ( 기본 적 으로 만든 행 저 장소 인덱스 를 실제로 바꿈 ) . The following code example creates ProductInventory as an in - memory system - versioned temporal table with a clustered columnstore index on the history table ( which actually replaces the row - store index created by default ) : 
 데이터베이스 에서 메모리 최적화 테이블 만들 기 가 허용 되 어야 합니다 . Make sure that your database allows creation of memory - optimized tables . 메모리 액세스 에 최적 화 된 테이블 및 고유 하 게 컴파일 된 저장 프로시저 만들 기 를 참조 하 세요 . See Creating a Memory - Optimized Table and a Natively Compiled Stored Procedure . 
 USE TemporalProductInventory 
 -- If table is system - versioned , SYSTEM _ VERSIONING must be set to OFF first 
 DROP TABLE IF EXISTS [ dbo ] . [ ProductInventory ] 
 DROP TABLE IF EXISTS [ dbo ] . [ ProductInventoryHistory ] 
 CREATE TABLE [ dbo ] . [ ProductInventory ] 
 SysStartTime datetime 2 ( 0 ) GENERATED ALWAYS AS ROW START NOT NULL , 
 SysEndTime datetime 2 ( 0 ) GENERATED ALWAYS AS ROW END NOT NULL , 
 PERIOD FOR SYSTEM _ TIME ( SysStartTime , SysEndTime ) , 
 -- Primary key definition 
 CONSTRAINT PK _ ProductInventory PRIMARY KEY NONCLUSTERED ( ProductId , LocationId ) 
 CREATE CLUSTERED COLUMNSTORE INDEX IX _ ProductInventoryHistory ON [ ProductInventoryHistory ] 
 다음 은 위 의 모델 에서 인벤토리 유지 관리 에 대한 절차 가 수행 되 는 방식 을 보여 줍니다 . For the model above this is how the procedure for maintaining inventory could look like : 
 CREATE PROCEDURE [ dbo ] . [ spUpdateInventory ] 
 @ quantityIncrement int 
 UPDATE dbo . ProductInventory 
 / * If zero rows were updated than this is insert of the new product for a given location */ 
 IF @ quantityIncrement < 0 
 INSERT INTO [ dbo ] . [ ProductInventory ] 
 , @ locationId 
 , @ quantityIncrement 
 SpUpdateInventory 저장 프로시저 에서 는 인벤토리 에 새 제품 을 삽입 하 거나 특정 위치 에 대한 제품 수량 을 업데이트 합니다 . The spUpdateInventory stored procedure either inserts a new product in the inventory or updates the product quantity for the particular location . 비즈니스 논리 는 매우 간단 하 며 , 테이블 업데이트 를 통해 수량 필드 를 증분 / 감소 시켜 항상 최신 상태 를 정확 하 게 유지 하 는 데 중점 을 둡니다 . 반면 시스템 버전 관리 된 테이블 은 아래 다이아그램 에 표시 된 대로 데이터 에 기록 차원 을 투명 하 게 추가 합니다 . The business logic is very simple and focused on maintaining the latest state accurate all the time by incrementing / decrementing the Quantity field through table update , while system - versioned tables transparently add history dimension to the data , as depicted on the diagram below 
 이제 최신 상태 에 대한 쿼리 를 네이티브 컴파일 모듈 에서 효율 적 으로 수행 할 수 있 습니다 . Now , querying of the latest state can be performed efficiently from the natively compiled module : 
 CREATE PROCEDURE [ dbo ] . [ s p QueryInventoryLatestState ] 
 SELECT ProductId , LocationID , Quantity , SysStartTime 
 FROM dbo . ProductInventory 
 ORDER BY ProductId , LocationId 
 시간 의 흐름 에 따라 데이터 변경 을 분석 하 는 작업 은 다음 예 에서 와 같이 FOR SYSTEM _ TIME ALL 절 을 사용 하 면 매우 간편 해집니다 . Analyzing data changes over time becomes extremely easy with the FOR SYSTEM _ TIME ALL clause , as shown in the following example : 
 CREATE VIEW vw _ G etProductInventoryHistory 
 SELECT ProductId , LocationId , Quantity , SysStartTime , SysEndTime 
 FROM [ dbo ] . [ ProductInventory ] 
 SELECT * FROM vw _ G etProductInventoryHistory 
 아래 다이어그램 은 파워 쿼리 , Power BI 또는 유사 한 비즈니스 인텔리 전 스 도구 에서 위 의 보기 를 가져와 쉽 게 렌더링 할 수 있 는 제품 한 개 에 대한 데이터 기록 을 보여 줍니다 . The diagram below shows the data history for one product which can be easily rendered importing the view above in the Power Query , Power BI or similar business intelligence tool : 
 이 시나리오 에서 는 임시 테이블 을 사용 하 여 과거 의 지정 시간 을 기준 으로 인벤토리 상태 를 다시 생성 하 거나 다른 시간 에 속해 있 는 스냅숏 을 비교 하 는 작업 과 같이 다른 형식 의 시간 이동 분석 을 수행 합니다 . Temporal tables can be used in this scenario to perform other types of time travel analysis , such as reconstructing the state of the inventory AS OF any point in time in the past or comparing snapshots that belong to different moments in time . 
 이 사용 시나리오 의 경우 Product 및 Location 테이블 을 확장 하 여 temporal 테이블 로 설정 할 수 도 있 습니다 . 이렇게 하 면 UnitPrice 및 NumberOfEmployee 의 변경 기록 을 나중 에 분석 할 수 있 습니다 . For this usage scenario , you can also extend the Product and Location tables to become temporal tables , which enables later analysis of the history of changes of UnitPrice and NumberOfEmployee . 
 SysStartTime datetime 2 ( 2 ) GENERATED ALWAYS AS ROW START HIDDEN 
 , SysEndTime datetime 2 ( 2 ) GENERATED ALWAYS AS ROW END HIDDEN 
 ALTER TABLE [ Location ] 
 constraint DFValidFrom DEFAULT DATEADD ( second , - 1 , SYSUTCDATETIME ( ) ) 
 constraint DFValidTo DEFAULT ' 9999 . 12 . 31 23 : 59 : 59 . 99 ' 
 데이터 모델 은 이제 여러 개 의 temporal 테이블 에 연결 되 므로 시점 기준 분석 을 위해서 는 관련 테이블 에서 필요 한 데이터 를 추출 하 는 보기 를 만들 고 , 이 보 기에 FOR SYSTEM _ TIME AS OF 를 적용 하 는 것 이 가장 좋 습니다 . 이렇게 하 면 전체 데이터 모델 상태 가 매우 간편 하 게 다시 생성 됩니다 . Since the data model now involves multiple temporal tables , the best practice for AS OF analysis is to create a view that extracts necessary data from the related tables and apply FOR SYSTEM _ TIME AS OF to the view as this will greatly simplify reconstructing the state of entire data model : 
 CREATE VIEW vw _ ProductInventoryDetails 
 SELECT PrInv . ProductId , PrInv . LocationId , P . ProductName , L . LocationName , PrInv . Quantity 
 , P . UnitPrice , L . NumberOfEmployees 
 , P . SysStartTime AS ProductStartTime , P . SysEndTime AS ProductEndTime 
 , L . SysStartTime AS LocationStartTime , L . SysEndTime AS LocationEndTime 
 , PrInv . SysStartTime AS InventoryStartTime , PrInv . SysEndTime AS InventoryEndTime 
 FROM dbo . ProductInventory as PrInv 
 SELECT * FROM vw _ ProductInventoryDetails 
 다음 그림 에서 는 SELECT 쿼리 에 대해 생성 된 실행 계획 을 보여 줍니다 . The following picture shows the execution plan generated for the SELECT query . 임시 관계 를 처리 하 는 모든 복잡 한 작업 들 이 SQL Server 엔진 에서 완벽 하 게 처리 되 는 것 을 확인 할 수 있 습니다 . This illustrates that all complexity of dealing with temporal relations is fully handled by the SQL Server engine : 
 다음 코드 를 사용 하 여 두 지정 시간 간 ( 하루 전 및 한 달 전 ) 제품 인벤토리 의 상태 를 비교 합니다 . Use the following code to compare state of product inventory between two points in time ( a day ago and a month ago ) : 
 inventoryDayAgo . ProductId 
 , inventoryDayAgo . ProductName 
 , inventoryDayAgo . LocationName 
 , inventoryDayAgo . Quantity AS QuantityDayAgo , inventoryMonthAgo . Quantity AS QuantityMonthAgo 
 , inventoryDayAgo . UnitPrice AS UnitPriceDayAgo , inventoryMonthAgo . UnitPrice AS UnitPriceMonthAgo 
 FROM vw _ ProductInventoryDetails 
 FOR SYSTEM _ TIME AS OF @ dayAgo AS inventoryDayAgo 
 JOIN vw _ ProductInventoryDetails FOR SYSTEM _ TIME AS OF @ monthAgo AS inventoryMonthAgo 
 변칙 검색 Anomaly Detection 
 변칙 검색 ( 또는 이상 값 검색 ) 은 예상 되 는 패턴 을 준 수 하 지 않 는 항목 또는 데이터 집합 의 다른 항목 ID 입니다 . Anomaly detection ( or outlier detection ) is the identification of items which do not conform to an expected pattern or other items in a dataset . 
 임시 쿼리 를 활용 하 면 특정 패턴 을 쉽 게 찾 을 수 있 으므로 시스템 버전 관리 된 temporal 테이블 을 사용 하 여 주기 적 으로 또는 불 규칙 적 으로 발생 하 는 변칙 을 검색 할 수 있 습니다 . You can use system - versioned temporal tables to detect anomalies that occur periodically or irregularly as you can utilize temporal querying to quickly locate specific patterns . 
 변칙 은 수집 하 는 데이터 형식 과 비즈니스 논리 에 따라 달라집니다 . What anomaly is depends on type of data you collect and your business logic . 
 다음 예제 에서 는 " 급증 " 판매량 을 검색 하 는 간단 한 논리 를 보여 줍니다 . The following example shows simplified logic for detecting “ spikes ” in sales numbers . 구매 한 제품 의 기록 을 수집 하 는 temporal 테이블 에서 작업 한다고 가정 해 봅니다 . Let ’ s assume that you work with a temporal table that collects history of the products purchased : 
 [ ProdID ] [ int ] NOT NULL PRIMARY KEY CLUSTERED 
 , [ ProductName ] [ varchar ] ( 100 ) NOT NULL 
 , [ DailySales ] INT NOT NULL 
 , [ ValidFrom ] [ datetime 2 ] ( 7 ) GENERATED ALWAYS AS ROW START NOT NULL 
 , [ ValidTo ] [ datetime 2 ] ( 7 ) GENERATED ALWAYS AS ROW END NOT NULL 
 , PERIOD FOR SYSTEM _ TIME ( [ ValidFrom ] , [ ValidTo ] ) 
 다음 다이어그램 에서 는 시간 의 흐름 에 따라 발생 한 구매 를 보여 줍니다 . The following diagram shows the purchases over time : 
 일상 기간 동안 에 는 구매 한 제품 수 의 차이 가 적 다고 가정 하 면 다음 쿼리 에서 는 단일 이상 값 이 식별 됩니다 . 바로 인접 해 있 는 값 과 비교 할 때 차이 가 큰 샘플 ( 2 배 ) 이 있 고 그 주변 샘플 들 은 상당 한 차이 를 보이 지 않 습니다 ( 20 % 미만 ) . Assuming that during the regular days number of purchased products has small variance , the following query identifies singleton outliers - samples which difference compared to their immediate neighbors is significant ( 2 x ) , while surrounding samples do not differ significantly ( less than 20 %): 
 WITH CTE ( ProdId , PrevValue , CurrentValue , NextValue , ValidFrom , ValidTo ) 
 ProdId , LAG ( DailySales , 1 , 1 ) over ( partition by ProdId order by ValidFrom ) as PrevValue 
 , DailySales , LEAD ( DailySales , 1 , 1 ) over ( partition by ProdId order by ValidFrom ) as NextValue 
 , ValidFrom , ValidTo from Product 
 , PrevValue 
 , CurrentValue 
 , NextValue 
 , ValidFrom 
 , ValidTo 
 , ABS ( PrevValue - NextValue ) / convert ( float , ( CASE WHEN NextValue > PrevValue THEN PrevValue ELSE NextValue END ) ) as PrevToNextDiff 
 , ABS ( CurrentValue - PrevValue ) / convert ( float , ( CASE WHEN CurrentValue > PrevValue THEN PrevValue ELSE CurrentValue END ) ) as CurrentToPrevDiff 
 , ABS ( CurrentValue - NextValue ) / convert ( float , ( CASE WHEN CurrentValue > NextValue THEN NextValue ELSE CurrentValue END ) ) as CurrentToNextDiff 
 ABS ( PrevValue - NextValue ) / ( CASE WHEN NextValue > PrevValue THEN PrevValue ELSE NextValue END ) < 0 . 2 
 AND ABS ( CurrentValue - PrevValue ) / ( CASE WHEN CurrentValue > PrevValue THEN PrevValue ELSE CurrentValue END ) > 2 
 이 예 는 의도 적 으로 단순 화 되 었 습니다 . This example is intentionally simplified . 프로덕션 시나리오 에서 는 고급 통계 방법 을 사용 하 여 공통 패턴 을 따르 지 않 는 샘플 을 식별 할 수 있 습니다 . In the production scenarios , you would likely use advanced statistical methods to identify samples which do not follow the common pattern . 
 느린 변경 차원 Slowly - Changing Dimensions 
 데이터 웨 어 하우징 에서 차원 은 일반 적 으로 지리 위치 , 고객 또는 제품 과 같 은 엔터 티 에 대한 비교 적 정적 데이터 를 포함 합니다 . Dimensions in data warehousing typically contain relatively static data about entities such as geographical locations , customers , or products . 그러나 일부 시나리오 의 경우 차원 테이블 에서 도 데이터 변경 사항 을 추적 해야 합니다 . However , some scenarios require you to track data changes in dimension tables as well . 예측 가능 하 지 않 은 방법 을 사용 하 고 , 팩 트 테이블 에 적용 되 는 정기 업데이트 일정 에서 벗어난 경우 차원 의 수정 발생 빈도 가 매우 낮 아 지 는 것 을 고려 할 때 이러 한 차원 테이블 형식 을 SCD ( 느린 변경 차원 ) 라고 합니다 . Given that modification in dimensions happen much less frequently , in unpredictable manner and outside of the regular update schedule that applies to fact tables , these types of dimension tables are called slowly changing dimensions ( SCD ) . 
 변경 기록 이 유지 되 는 방법 에 따라 느린 변경 차원 범주 가 몇 가지 있 습니다 . There are several categories of slowly changing dimensions based on how history of changes is preserved : 
 유형 0 : 기록 이 유지 되 지 않 습니다 . Type 0 : History is not preserved . 차원 특성 은 원래 값 을 반영 합니다 . Dimension attributes reflect original values . 
 유형 1 : 차원 특성 이 최신 값 을 반영 합니다 ( 이전 값 은 덮 어 씀 ) . Type 1 : Dimension attributes reflect latest values ( previous values are overwritten ) 
 유형 2 : 모든 버전 의 차원 멤버 가 유효 기간 을 나타내 는 열 이 포함 된 테이블 에서 별도 의 행 으로 나타납니다 . Type 2 : Every version of dimension member represented with separate row in the table usually with columns that represent period of validity 
 유형 3 : 동일 한 행 에서 추가 열 을 사용 하 여 선택 한 특성 에 대해 제한 된 기록 을 유지 합니다 . Type 3 : Keeping limited history for selected attribute ( s ) using additional columns in the same row 
 유형 4 : 원래 차원 테이블 에서 최신 ( 현재 ) 차원 멤버 버전 을 유지 하 는 동안 별도 의 테이블 에서 기록 을 유지 합니다 . Type 4 : Keeping history in the separate table while original dimension table keeps latest ( current ) dimension member versions 
 SCD 전략 을 선택 할 때 주로 많 은 코드 와 복잡 한 유지 관리 가 필요 한 차원 테이블 을 정확 하 게 유지 하 는 책임 은 ETL ( 추출 - 변환 - 로드 ) 계층 에 있 습니다 . When you choose SCD strategy , it is responsibility of the ETL layer ( Extract - Transform - Load ) to keep dimension table ( s ) accurate and that usually requires a lot of code and complex maintenance . 
 SQL Server 2016 에서 시스템 버전 관리 된 temporal 테이블 을 사용 하 면 데이터 기록 이 자동 으로 유지 되 므로 코드 의 복잡 성 을 획기적으로 줄일 수 있 습니다 . System - versioned temporal tables in SQL Server 2016 can be used to dramatically lower the complexity of your code as history of data is automatically preserved . 두 테이블 을 사용 하 는 구현 방법 을 고려 해 볼 때 SQL Server 2016 에서 temporal 테이블 은 SCD 유형 4 에 가장 가깝 습니다 . Given its implementation using two tables , temporal tables in SQL Server 2016 is closest to Type 4 SCD . 그러나 임시 쿼리 를 사용 하 면 현재 테이블 만 참조 할 수 있 으므로 SCD 유형 2 사용 을 계획 하 는 환경 에서 temporal 테이블 을 고려 해 볼 수 도 있 습니다 . However , since temporal queries allows you to reference current table only , you can also consider temporal tables in environments where you plan to use Type 2 SCD . 
 일반 차원 을 SCD 로 변환 하 려면 새 테이블 을 만들 거나 기존 테이블 을 시스템 버전 관리 된 temporal 테이블 로 변경 하 기 만 하 면 됩니다 . In order to convert your regular dimension to SCD , just create a new one or alter an existing one to become a system - versioned temporal table . 기존 차원 테이블 에 기록 데이터 가 있 는 경우 별도 테이블 을 만들 고 기록 데이터 를 이동 하 여 현재 ( 실제 ) 차원 버전 을 원래 차원 테이블 에서 유지 합니다 . If your existing dimension table contains historical data , create separate table and move historical data there and keep current ( actual ) dimension versions in your original dimension table . 그런 다음 ALTER TABLE 구문 을 사용 하 여 미리 정의 된 기록 테이블 이 있 는 시스템 버전 관리 된 temporal 테이블 에 차원 테이블 을 변환 합니다 . Then use ALTER TABLE syntax to convert your dimension table to a system - versioned temporal table with a predefined history table . 
 다음 예제 에서 는 해당 프로세스 에 대해 설명 하 고 , DimLocation 차원 테이블 에 ETL 에서 채워지 는 datetime 2 의 null 이 아닌 열 로 ValidFrom 과 ValidTo 가 있 다고 가정 합니다 . The following example illustrates the process and assumes that the DimLocation dimension table already has ValidFrom and ValidTo as datetime 2 non - nullable columns which are populated by the ETL process : 
 / * Move “ closed ” row versions into newly created history table */ 
 SELECT * INTO DimLocationHistory 
 FROM DimLocation 
 / * Create clustered columnstore index which is a very good choice in DW scenarios */ 
 CREATE CLUSTERED COLUMNSTORE INDEX IX _ DimLocationHistory ON DimLocationHistory 
 / * Delete previous versions from DimLocation which will become current table in temporal - system - versioning configuration */ 
 DELETE FROM DimLocation 
 / * Add period definition */ 
 / * Enable system - versioning and bind histiory table to the DimLocation */ 
 데이터 웨어 하우스 로딩 프로세스 중 에 SCD 를 유지 관리 하 기 위해 추가 코드 가 필요 하 지 않 습니다 . Note that no additional code is required to maintain SCD during the data warehouse loading process once you created it . 
 다음 그림 에서 는 SCD 2 개 ( DimLocation 과 DimProduct ) 와 팩 트 테이블 1 개 가 포함 된 간단 한 시나리오 에서 임시 테이블 을 사용 하 는 방법 에 대해 보여 줍니다 . The following illustration shows how you can use Temporal Tables in a simple scenario involving 2 SCDs ( DimLocation and DimProduct ) and one fact table . 
 위 의 SCD 를 보고서 에서 사용 하 려면 쿼리 를 효과 적 으로 조정 해야 합니다 . In order to use above SCDs in reports , you need to effectively adjust querying . 예 를 들 어 지난 6 개월 동안 1 인 당 판매 된 제품 수 의 평균 과 총 판매액 을 계산 할 수 있 습니다 . For example , you might want to calculate the total sales amount and the average number of sold products per capita for the last six months . 분석 에 중요 한 특성 을 변경 했 을 수 도 있 는 팩 트 테이블 과 차원 에서 의 데이터 의 상관 관계 가 두 메 트릭 에 모두 필요 합니다 ( DimLocation . NumOfCustomers , DimProduct . UnitPrice ) . Note that both metrics requires the correlation of data from the fact table and dimensions that might have changed their attributes important for the analysis ( DimLocation . NumOfCustomers , DimProduct . UnitPrice ) . 다음 쿼리 에서 는 필요 한 메트 릭 을 올바르 게 계산 합니다 . The followinq query properly calculates the required metrics : 
 DECLARE @ sixMonthsAgo datetime 2 SET 
 SELECT DimProduct _ History . ProductId 
 , DimLocation _ History . LocationId 
 , SUM ( F . Quantity * DimProduct _ History . UnitPrice ) AS TotalAmount 
 , AVG ( F . Quantity / DimLocation _ History . NumOfCustomers ) AS AverageProductsPerCapita 
 FROM FactProductSales F 
 / * find corresponding record in SCD history in last 6 months , based on matching fact */ 
 JOIN DimLocation FOR SYSTEM _ TIME BETWEEN @ sixMonthsAgo AND @ now AS DimLocation _ History 
 AND F . FactDate BETWEEN DimLocation _ History . ValidFrom AND DimLocation _ History . ValidTo 
 JOIN DimProduct FOR SYSTEM _ TIME BETWEEN @ sixMonthsAgo AND @ now AS DimProduct _ History 
 AND F . FactDate BETWEEN DimProduct _ History . ValidFrom AND DimProduct _ History . ValidTo 
 WHERE F . FactDate BETWEEN @ sixMonthsAgo AND @ now 
 고려 사항 : Considerations : 
 데이터베이스 트랜잭션 시간 을 기반 으로 계산 된 유효 성 검사 기간 이 비즈니스 논리 에 적합 한 경우 SCD 에 대한 시스템 버전 관리 된 temporal 테이블 을 사용 할 수 있 습니다 . Using system - versioned temporal tables for SCD is acceptable if period of validity calculated based on database transaction time is fine with your business logic . 데이터 를 로드 할 때 지연 시간 이 상당 한 경우 트랜잭션 시간 이 허용 되 지 않 을 수 있 습니다 . If you load data with significant delay , transaction time might not be acceptable . 
 기본 적 으로 시스템 버전 관리 된 temporal 테이블 에서 는 로딩 후 에 는 기록 데이터 를 변경 할 수 없 습니다 ( SYSTEM _ VERSIONING 을 OFF 로 설정 한 후 기록 수정 가능 ) . By default , system - versioned temporal tables do not allow changing historical data after loading ( you can modify history after you set SYSTEM _ VERSIONING to OFF ) . 기록 데이터 를 정기 적 으로 변경 하 는 경우 제한 이 있 을 수 있 습니다 . This might be limitation in cases where changing historical data happens regularly . 
 시스템 버전 관리 된 임시 테이블 에서 열 변경 시 행 버전 이 생성 됩니다 . Temporal system - versioned tables generate row version on any column change . 특정 열 변경 시 새 버전 을 표시 하 지 않 으려면 ETL 논리 에서 해당 제한 사항 을 통합 해야 합니다 . If you want to suppress new versions on certain column change you need to incorporate that limitation in the ETL logic . 
 SCD 테이블 에 기록 행 수 가 상당 할 것 으로 예상 되 는 경우 기록 테이블 의 주 저 장소 옵션 으로 클러스터 형 columnstore 인덱스 를 사용 하 는 것 이 좋 습니다 . If you expect a significant number of historical rows in SCD tables , consider using a clustered columnstore index as the main storage option for history table . 이렇게 하 면 기록 테이블 의 공간 이 줄어들 어 분석 쿼리 속도 가 빨라집니다 . That will reduce history table footprint and speed up your analytical queries . 
 행 수준 데이터 손상 복구 Repairing Row - Level Data Corruption 
 시스템 버전 관리 된 temporal 테이블 에서 기록 데이터 를 사용 하 여 개별 행 을 이전 에 캡 처 된 상태 로 빠르 게 복구 할 수 있 습니다 . You can rely on historical data in system - versioned temporal tables to quickly repair individual rows to any of the previously captured states . temporal 테이블 의 이 속성 은 영향 을 받 는 행 을 찾 거나 원 하 지 않 는 데이터 변경 시간 을 알 고 있 을 때 백업 을 처리 하 지 않 고 효율 적 으로 복구 를 수행 할 수 있 으므로 매우 유용 합니다 . This property of temporal tables is very useful when you are able to locate affected rows and / or when you know time of undesired data change so you can perform repair very efficiently without dealing with backups . 
 이 접근 방법 에 는 여러 가지 이점 이 있 습니다 . This approach has several advantages : 
 복구 범위 를 매우 정확 하 게 제어 할 수 있 습니다 . You are able to control the scope of the repair very precisely . 영향 을 받 지 않 는 레코드 는 최신 상태 로 유지 되 어야 하 며 , 종종 중요 하 게 요구 됩니다 . Records that are not affected need to stay at the latest state , which is often a critical requirement . 
 작업 이 매우 효율 적 이 며 데이터 를 사용 하 는 모든 작업 에 대해 데이터베이스 가 온라인 상태 로 유지 됩니다 . Operation is very efficient and the database stays online for all workloads using the data . 
 복구 작업 자체 가 버전 관리 입니다 . The repair operation itself is versioned . 복구 작업 자체 에 대한 감사 추적 이 가능 하 므로 필요 할 경우 나중 에 발생 한 내용 을 분석 할 수 있 습니다 . You have audit trail for repair operation itself , so you can analyze what happened later if necessary . 
 복구 작업 은 비교 적 쉽 게 자동 화 할 수 있 습니다 . Repair action can be automated relatively easily . 데이터 감사 시나리오 에 사용 되 는 Employee 테이블 에 대해 데이터 복구 를 수행 하 는 저장 프로시저 의 코드 예제 는 다음 과 같 습니다 . Here is code example of the stored procedure that performs data repair for the table Employee used in the data audit scenario . 
 CREATE PROCEDURE sp _ RepairEmployeeRecord 
 / * Order historical rows by tehir age in DESC order */ 
 SELECT ROW _ NUMBER ( ) OVER ( PARTITION BY EmployeeID ORDER BY [ ValidTo ] DESC ) AS RN , * 
 / * Update current row by using N - th row version from history ( default is 1 - i . e . last version ) */ 
 다음 그림 은 프로시저 호출 이전 및 이후 행 의 상태 를 보여 줍니다 . The following picture shows state of the row before and after the procedure invocation . 빨간색 직사각형 은 잘못 된 현재 행 버전 을 표시 하 고 , 녹색 직사각형 은 기록 에서 올바른 버전 을 표시 합니다 . Red rectangle marks current row version that is incorrect , while green rectangle marks correct version from the history . 
 이 복구 저장 프로시저 는 행 버전 대신 정확 한 타임스탬프 를 허용 하 도록 정의 할 수 있 습니다 . This repair stored procedure can be defined to accept an exact timestamp instead of row version . 이렇게 하 면 행이 제공 된 지정 시간 에 활성 상태 였 던 버전 으로 복원 됩니다 ( 예 : 지정 시간 기준 ) . It will restore row to any version that was active for the point in time provided ( i . e . AS OF point in time ) . 
 CREATE PROCEDURE sp _ RepairEmployeeRecordAsOf 
 @ asOf datetime 2 
 / * Update current row to the state that was actual AS OF provided date */ 
 동일 한 데이터 샘플 에 대해 다음 그림 은 시간 조건 이 포함 된 복구 시나리오 를 보여 줍니다 . For the same data sample the following picture illustrates repair scenario with time condition . @ asOf 매개 변수 , 제공 된 지정 시간 에 실제로 있 었 던 기록 에서 선택 한 행 , 그리고 복구 작업 후 현재 테이블 의 새 행 버전 이 강조 표시 되 어 있 습니다 . Highlighted are @ asOf parameter , selected row in the history that was actual at the provided point in time and new row version in the current table after repair operation : 
 데이터 수정 은 데이터 웨 어 하우징 및 보 고 시스템 에서 자동 화 된 데이터 로드 작업 에 포함 될 수 있 습니다 . Data correction can become part of automated data loading in data warehousing and reporting systems . 
 새로 업데이트 된 값 이 올바르 지 않 으면 여러 시나리오 에서 기록 에서 이전 버전 을 복원 하 는 것 이 문제 를 완화 시킬 수 있 는 충분 한 방법 입니다 . If a newly updated value is not correct then , in many scenarios , restoring the previous version from history is good enough mitigation . 다음 다이어그램 은 이 프로세스 를 자동 화 하 는 방법 을 보여 줍니다 . The following diagram shows how this process can be automated : 
 임시 테이블 을 사용 하 여 분할 Partitioning with Temporal Tables