데이터 아카이브는 대규모 테이블이 있는 고부하 OLTP 시스템의 가장 중요한 작업 중 하나입니다. 역사적으로 아카이브를 수행하기 위한 첫 번째 시도는 매우 간단했습니다: 데이터가 수동으로 스크립트나 애플리케이션을 통해 별도의 테이블로 삭제되거나 복사되었습니다. 이후에는 트랜잭션 무결성을 고려하고 기본 데이터베이스 작업에 대한 영향을 최소화하는 보다 체계적인 접근 방식이 등장했습니다.
여기서 문제는 정보를 물리적으로 이동하는 것뿐만 아니라 일관성을 유지하고, 차단을 최소화하며, 높은 성능을 보장하는 것입니다. 아카이브 중 오류는 데이터 손실, 사용자 차단 또는 부하 증가로 이어질 수 있습니다.
해결책으로는 트랜잭션 제어가 있는 배치 작업을 사용하는 것과 동일한 구조를 가진 특별한 아카이브 테이블을 만드는 것 또는 작업 스케줄러와 절차를 통한 자동화를 사용하는 것입니다.
코드 예:
-- 1년 이상 된 5000개 레코드를 아카이브 테이블로 이동 INSERT INTO archive_orders SELECT * FROM orders WHERE order_date < DATEADD(year, -1, GETDATE()) AND id IN (SELECT TOP 5000 id FROM orders WHERE order_date < DATEADD(year, -1, GETDATE()) ORDER BY id); DELETE FROM orders WHERE id IN (SELECT TOP 5000 id FROM orders WHERE order_date < DATEADD(year, -1, GETDATE()) ORDER BY id);
주요 특징:
오래된 레코드의 대량 DELETE 시 어떤 위험이 있으며 이를 피하는 방법은 무엇인가요?
대량 DELETE는 차단의 에스컬레이션을 초래하고 데이터베이스 전체의 작업을 지연시킬 수 있습니다. 이를 피하기 위해 작은 배치로 삭제하거나, 데이터베이스가 지원하는 경우 LIMIT/TOP을 사용하는 것이 좋습니다.
WHILE 1=1 BEGIN DELETE TOP (1000) FROM orders WHERE order_date < '2023-01-01'; IF @@ROWCOUNT = 0 BREAK; END
아카이브된 데이터를 삭제하는 데 TRUNCATE를 사용할 수 있나요?
TRUNCATE는 테이블의 모든 행을 삭제하며 특정 행의 조건부 삭제에는 적합하지 않습니다. 트리거를 호출하지 않고 WHERE를 지원하지 않으며 완전한 삭제에만 사용됩니다. 선택적 아카이브에는 적합하지 않습니다.
삭제와 삽입이 다른 트랜잭션에서 수행될 때 전송이 올바르게 수행되었는지 어떻게 보장하나요?
최우선 방법은 모든 작업을 하나의 트랜잭션에서 수행하는 것입니다: 먼저 아카이브로 복사한 후 기본 소스에서 삭제합니다. 그렇지 않으면 작업 간 장애로 인해 일관성이 깨질 수 있습니다.
BEGIN TRANSACTION INSERT INTO archive_orders SELECT * FROM orders WHERE ... DELETE FROM orders WHERE ... COMMIT
엔지니어가 근무 시간 중에 백만 개의 레코드에 대해 DELETE FROM logs WHERE event_date < '2022-01-01' 스크립트를 실행합니다.
장점:
단점:
저녁에 5000개 행을 전송하도록 계획하고 저장 프로시저와 작업 스케줄을 통해 성공적인 각 배치를 기록함.
장점:
단점: