SQL Server DELAYED_DURABILITY 옵션으로 트랜잭션 로그 쓰기 성능 개선 하기

 

l  Version : SQL Server

 

SQL Server 데이터베이스에는 모든 트랜잭션과 트랜잭션에 의해 적용된 데이터베이스 수정 내용을 기록하는 트랜잭션 로그가 있다. 트랜잭션 로그는 데이터베이스의 매우 중요한 요소로 시스템 오류가 발생한 경우 데이터베이스를 일관된 상태로 다시 전환하려면 로그가 필요하다.

l  트랜잭션 로그 아키텍처 : https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-transaction-log-architecture-and-management-guide?view=sql-server-ver16

 

데이터베이스에 대량의 쓰기 작업이 발생하면 트랜잭션 로그에는 변경사항을 기록하기 위해 오버헤드가 발생하면서 로그 쓰기 작업(Write Log) 지연되는 경우가 발생한다. 로그 모니터링을 통하여 Write Log 지연이 발생할 경우 DELAYED_DURABILITY 옵션을 사용하여 해당 문제를 개선할 있다. 옵션을 사용할 경우 트랜잭션 로그의 커밋을 기다리지 않기 때문에 워크로드의 대기 시간이 줄어들어 성능 개선은 있지만 트랜잭션 데이터를 소실할 있기 때문에 주의해서 사용해야 한다. 이번 포스트에서는 DELAYED_DURABILITY 옵션에 대한 특징을 살펴보고, 어떠한 경우에 사용할 있는지 살펴본다.

 

SQL Server 트랜잭션 로그 파일에 데이터를 저장해야 트랜잭션 로그 파일이 저장된 디스크에 직접 데이터를 기록하지 않는다. 대신 모든 데이터는 인메모리 구조인 로그 캐시(로그 버퍼, 또는 로그 블록 이라고 불리기도 한다.) 직렬로 기록된다. 또한 SQL Server OS ACID 원칙을 준수해야 하므로 전체 로그 캐시를 디스크 하위 시스템에 저장하거나 필요한 경우 롤백 되는 트랜잭션 로그 파일로 플러시 한다. 로그 캐시의 크기는 512B ~ 64KB이다.

 

로그 캐시는 특정 조건에서 디스크로 플러시 된다.

l  트랜잭션이 커밋될

l  로그 캐시가 가득 차서 60KB 도달했을

l  Sys.sp_flush_log 실행될

l  CHECKPOINT 프로세스가 완료 되었을

 

SQL Server 로그 캐시가 트랜잭션 로그 파일로 플러시 되기 시작하는 순간 WRITELOG 대기 유형에 등록되고 로그 캐시가 메모리에서 디스크 드라이브의 파일로 데이터 플러시를 완료 때까지 해당 시간이 누적된다. 누적시간이 낮을수록 트랜잭션 로그파일의 쓰기 대기 시간이 낮아 진다.

 

SQL Server에서는 기본적으로 동기 트랜잭션 커밋을 사용하기 때문에 트랜잭션에 대한 로그 레코드가 디스크에 기록된 후에만 커밋을 성공으로 보고하고 클라이언트에 컨트롤을 반환한다. 따라서 이러한 커밋이 느릴수록 클라이언트에서는 느린 응답을 받을 수밖에 없다. 동기 커밋은 아래와 같은 완전 내구성이 있는 환경의 경우 필수적으로 사용해야한다.

l  시스템에서 데이터 손실을 허용할 없는 경우

l  병목 현상의 원인이 트랜잭션 로그 쓰기 대기 시간이 아닌 경우

 

DELAYED_DURABILITY 옵션을 활성화 경우, 비동기 트랜잭션 커밋을 사용하기 때문에 트랜잭션에 대한 로그 레코드가 디스크에 기록되기 전에 커밋 성공으로 클라이언트에 컨트롤을 반환하기 때문에 클라이언트에서는 빠른 응답을 얻을 있다. 또한 동시 트랜잭션의 로그 I/O 경합 가능성이 낮아지고, 청크 구성으로 디스크에 플러시하여 경합을 줄이고 처리 속도를 높일 있다. 비동기 커밋의 경우 아래와 같은 환경에서 사용할 있다.

l  약간의 데이터 손실을 허용하는 경우

l  트랜잭션 로그 쓰기 중에 병목 현상이 발생하는 경우

l  작업의 경합률이 높은 경우

 

DELAYED_DURABILITY 옵션은 데이터베이스 수준에서 트랜잭션 내구성 수준을 제어할 있다. 아래 스크립트는 DELAYED_DURABILITY 옵션을 데이터베이스 수준에서 변경한다.

ALTER DATABASE ... SET DELAYED_DURABILITY = { DISABLED | ALLOWED | FORCED }

 

l  DISABLED : 기본값으로 커밋 수준 설정 (DELAYED_DURABILITY={ON|OFF}) 상관없이 데이터베이스 커밋된 모든 트랜잭션이 완전 내구성을 가진다. 저장 프로시저를 변경하고 다시 컴파일할 필요가 없다. 지연된 내구성으로 인해 데이터가 위험에 노출되지 않는다.

l  ALLOWED : 트랜잭션의 내구성이 트랜잭션 수준에서 결정된다. 커밋 수준 설정 (DELAYED_DURABILITY={ON|OFF}) 의해 결정된다.

l  FORCED : 데이터베이스에 커밋되는 모든 트랜잭션이 지연된 내구성을 가진다. 설정은 지연된 트랜잭션 내구성이 데이터베이스에 유용하고 어플리케이션 코드를 변경하지 않으려는 경우에 유용하다.

 

 

아래 스크립트는 커밋 수준을 설정한다.

DELAYED_DURABILITY = { OFF | ON }

 

l  OFF : 기본값으로 DELAYED_DURABILITY = FORCED 데이터베이스 옵션을 적용하여 커밋이 비동기적이고 지연된 내구성을 갖는 경우를 제외하고 트랜잭션은 완전 내구성을 가진다.

l  ON : DELAYED_DURABILITY = FORCED 데이터베이스 옵션을 적용하여 커밋이 동기적으로 완전 내구성있는 경우를 제외하고 트랜잭션은 지연된 내구성을 가진다.

 

아래 스크립트는 저장 프로시저에 커밋 수준을 적용한 예시이다.

CREATE PROCEDURE [<procedureName>] /* parameters go here */
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER   
AS BEGIN ATOMIC WITH    
(   
    DELAYED_DURABILITY = ON,   
    TRANSACTION ISOLATION LEVEL = SNAPSHOT,   
    LANGUAGE = N'English'   
)   
/* procedure body goes here */
END

 

 

지연된 트랜잭션 내구성을 강제로 적용할 있도록 COMMIT 구문으로도 확장할 있는데, 데이터베이스 수준에서 DELAYED_DURABILITY DISABLED 또는 FORCED 경우 COMMIT 옵션은 무시된다.

COMMIT [ { TRAN | TRANSACTION } ] [ transaction_name | @tran_name_variable ] ] [ WITH ( DELAYED_DURABILITY = { OFF | ON } ) ]

 

l  OFF : 기본값으로 DELAYED_DURABILITY = FORCED 데이터베이스 옵션을 적용하여 CIMMIT 비동기 적으로 지연된 내구성을 갖는 경우를 제외하고 COMMIT 트랜잭션은 완전 내구성을 가진다.

l  ON : DELAYED_DURABILITY = DISABLED 데이터베이스 옵션을 적용하여 COMMIT 동기적이고 완전 내구성 있는 경우를 제외하고 COMMIT 트랜잭션은 지연된 내구성을 가진다.

 

 

지연된 내구성을 사용할 경우 특정 상황에서 데이터를 손실 가능성이 있기 때문에 반드시 해당 비즈니스의 목적과 데이터베이스 성능 등을 고려하여 사용 여부를 결정할 있도록 한다.

 

[참고자료]

l  Control Transaction Durability : https://learn.microsoft.com/en-us/sql/relational-databases/logs/control-transaction-durability?view=sql-server-ver16

l  Measure Delayed Durability impact in SQL Server 2016 and later : https://www.mssqltips.com/sqlservertip/6355/measure-delayed-durability-impact-in-sql-server-2016-and-later/

l  Get SQL Server Delayed Durability Advantages Without Configuration Changes : https://www.mssqltips.com/sqlservertip/6324/get-sql-server-delayed-durability-advantages-without-configuration-changes/

l  How to handle the SQL Server WRITELOG wait type : https://www.sqlshack.com/how-to-handle-the-sql-server-writelog-wait-type/

l  Improve SQL Server transaction log performance with Delayed Durability : https://www.sqlshack.com/improve-sql-server-transaction-log-performance-with-delayed-durability/

l  The Transaction Log (SQL Server) : https://learn.microsoft.com/en-us/sql/relational-databases/logs/the-transaction-log-sql-server?view=sql-server-ver16

l  SQL Server Transaction Log Architecture and Management Guide : https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-transaction-log-architecture-and-management-guide?view=sql-server-ver16

 

 

 

2022-10-30/ Sungwook Kang / http://sungwookkang.com

 

 

 

SQL Server, MS SQL, DELAYED_DURABILITY, 트랜잭션 로그 비동기 커밋, WAL, Write Log

SQL Server 에서 AWS S3 직접 백업하기

 

l  Version : SQL Server 2022

 

SQL Server 2022부터는 데이터 플랫폼에 통합 오브젝트 스토리지를 도입하여 Azure Storage외에도 AWS S3 호환 오브젝트 스토리지도 사용할 있다. , SQL Server에서 AWS S3 직접 백업을 있게 되었다.

기존 SQL Server 2019 경우 Microsoft Azure 저장소만 가능 하였다. SQL Server 2022 부터 도입된 S3 REST API SQL Server에서 AWS S3 직접 백업, 복원을 있어, 백업 이동에 따른 프로세스 단축 대용량 백업을 진행할 경우에도 로컬 공간이 부족하여도 백업을 진행할 있게 되었다.

 

지원되는 백업 종류

l  전체 백업

l  차등 백업

l  트랜잭션 로그 백업

l  복사 전용 백업 (COPY ONLY)

 

지원되지 않는 백업 종류

l  스냅샷 백업 (FILE_SNAPSHOT)

l  미러 백업 (MIRROR)

 

AWS S3버킷으로 백업 복원을 수행 하기위해서는 아래 정보가 필요 하다.

l  S3 버킷이름

l  S3 URI

l  S3 URL

l  IAM 액세스 ID

l  IAM 액세스

 

AWS IAM(Idnetity Access Management) 정책은 사용자의 권한 또는 특정 서비스에 대해 수행할 있는 역할을 정의한다. SQL Server 2022에서 S3 버킷으로 직접 데이터베이스 백업을 수행하려면 ListBucket PutObject 권한이 필요하다.

l  ListBucket : ListBucket 액세스는 요청의 인증된 발신자가 소유한 모든 버킷 목록을 반환한다.

l  PutObject : PutObject 액세스를 통해 버킷에 객체를 작성하고 추가할 있다.

 

SQL Server에서 AWS S3 백업을 하기 위해 우선 자격증명을 만들어야 한다. 아래는 자격증명을 만드는 스크립트이다.

CREATE CREDENTIAL   [s3://<endpoint>:<port>/<bucket>]
WITH   
        IDENTITY    = 'S3 Access Key',
        SECRET      = '<AccessKeyID>:<SecretKeyID>';

 

l  [s3://<endpoint>:<port>/<bucket>] : 자격 증명 이름에는 S3 버킷 이름이 포함되어야 한다. S3:// 시작하고 접두사 HTTPS:// 제거한 S3 버킷 URL 따른다.

l  IDENTITY : S3 Access Key 값으로, 자격 증명에서 S3 커넥터를 사용하고 있음을 나타낸다.

l  SECRET : 접근키 ID 비밀 키를 콜론으로 구분하여 입력한다. 콜론 기호는 구분자 역할을 한다.  

 

 

 

백업 명령은 기존에 사용하던 백업문과 거의 동일하다. 다만 백업 위치가 DISK 아닌 URL 사용한다.

BACKUP DATABASE [DatabaseName] TO URL = 'CredentialName\Backupfilename.bak'

 

 

백업 완료 S3 확인해보면 백업파일이 생성된 것을 확인할 있다.

 

아래 스크립트는 백업하려는 데이터베이스를 여러 스트라이프된 백업 파일로 오브젝트 스토리지 엔드포인트를 사용하여 백업을 수행한다.

BACKUP DATABASE <db_name>
TO      URL = 's3://<endpoint>:<port>/<bucket>/<database>_01.bak'
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_02.bak'
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_03.bak'
--
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_64.bak'
WITH    FORMAT -- overwrite
,       STATS               = 10
,       COMPRESSION;

 

 

 

아래 스크립트는 오브젝트 스토리지 엔드포인트 위치에서 데이터베이스 복원을 수행한다.

RESTORE DATABASE <db_name>
FROM    URL = 's3://<endpoint>:<port>/<bucket>/<database>_01.bak'
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_02.bak'
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_03.bak'
--
,       URL = 's3://<endpoint>:<port>/<bucket>/<database>_64.bak'
WITH    REPLACE -- overwrite
,       STATS = 10;

 

 

데이터를 저장하려면 S3 호환 오브젝트 스토리지 공급자는 파트(Part) 불리는 여러 블록으로 파일을 분할해야 한다. 파일은 최대 10,000개의 파트로 분할 있으며, 파트의 크기는 5MB ~ 20MB이다. 범위는 매개변수 MAXTRANSFERSIZE 통해 T-SQL BACKUP 명령으로 제어할 있다. MAXTRANSFERSIZE 기본값은 10MB 이므로 파트의 기본 크기는 10MB이다.  , 단일 백업 파일의 크기는 MAXTRANSFERSIZE 기본값으로 설정되어 있을 경우 100,000MB이다. 백업 스트라이프가 100,000MB 초과할 경우 아래와 같은 오류 메시지를 반환한다.

Msg 3202, Level 16, State 1, Line 161
Write on 's3://<endpoint>:<port>/<bucket>/<path>/<db_name>.bak' failed: 87(The parameter is incorrect.)
Msg 3013, Level 16, State 1, Line 161
BACKUP DATABASE is terminating abnormally.

 

단일 백업 파일의 크기가 100,000MB 보다 파일을 백업 해야 경우 최대 64개의 URL 스트라이프 백업을 지원한다. , 가능한 최대 백업 파일 크기는 10,000part * MAXTRANSFERSIZE * URL이다. 압축 백업을 사용할 경우 백업 파일 사이즈가 현저히 많이 줄어들기 때문에 백업 압축 옵션을 적극 활용할 있도록 한다.

아래 예제는 MAXTRANSFERSIZE 사용하여 20MB으로 설정하고, 백업 압축 암호화한다.

CREATE MASTER KEY ENCRYPTION BY PASSWORD = <password>;
GO
 
CREATE CERTIFICATE AdventureWorks2019Cert
    WITH SUBJECT = 'AdventureWorks2019 Backup Certificate';
GO
-- Backup database
BACKUP DATABASE AdventureWorks2019
TO URL = 's3://<endpoint>:<port>/<bucket>/AdventureWorks2019_Encrypt.bak'
WITH FORMAT, MAXTRANSFERSIZE = 20971520, COMPRESSION,
ENCRYPTION (ALGORITHM = AES_256, SERVER CERTIFICATE = AdventureWorks2019Cert)
GO

 

백업 복원 엔진에서 URL 길이는 259바이트로 제한되어 있기 때문에 s3:// 제외하고 사용자의 경로 길이(호스트 이름 + 개체키) 259 - 5 = 254글자까지 입력할 있다. 만약 URL 길이를 초과할 경우 아래와 같은 오류가 반환된다.

SQL Server has a maximum limit of 259 characters for a backup device name. The BACKUP TO URL consumes 36 characters for the required elements used to specify the URL - 'https://.blob.core.windows.net//.bak', leaving 223 characters for account, container, and blob names put together'

 

S3 스토리지는 SQL 호스트와 S3 서버간의 시간 차이가 15분을 초과할 마다 연결을 거부하고 “InvalidSignatureException”오류를 SQL Server 보낸다. SQL Server에서는 아래와 같은 오류로 반환된다.

Msg 3201, Level 16, State 1, Line 28
Cannot open backup device '<path>'. Operating system error 5(Access is denied.).
Msg 3013, Level 16, State 1, Line 28
BACKUP DATABASE is terminating abnormally.

 

 

[참고자료]

l  SQL Server backup to URL for S3-compatible object storage : https://learn.microsoft.com/en-us/sql/relational-databases/backup-restore/sql-server-backup-to-url-s3-compatible-object-storage?view=sql-server-ver16

l  SQL Server back up to URL for S3-compatible object storage best practices and troubleshooting : https://learn.microsoft.com/ko-kr/sql/relational-databases/backup-restore/sql-server-backup-to-url-s3-compatible-object-storage-best-practices-and-troubleshooting?view=sql-server-ver16

l  https://www.mssqltips.com/sqlservertip/7301/sql-server-2022-backup-restore-aws-s3-storage/

l  https://www.mssqltips.com/sqlservertip/7302/backup-sql-server-2022-database-aws-s3-storage/

 

 

 

2022-10-28/ Sungwook Kang / http://sungwookkang.com

 

 

 

SQL Server, MS SQL, AWS S3 backup, S3 백업, 클라우드 백업, cloud backup

[AWS Aurora] Aurora PostgreSQL Auto Vacuum 이해하기

 

l  Version : AWS Aurora PostgreSQL

 

PostgreSQL 오픈소스 관계형 데이터베이스로 AWS PostgreSQL 오픈소스 데이터베이스를 완전 관리형 데이터베이스 서비스로 제공한다.

l  Amazon Aurora : https://aws.amazon.com/ko/rds/aurora/

 

많은 사용자들이 PostgreSQL(이하 PG) 사용할 Vacuum 동작으로 인해 예상하지 못한 성능 하락 문제를 겪고 있는데 Vacuum 수행되었을 발생하는 문제는 무엇이 있는지, 그리고 이러한 문제를 최소화하기 위한 전략이 무엇이 있는지에 대해서 알아본다.

 

[Vacuum 하는 것일까]

Vacuum 일반 적으로 진공 청소기라는 뜻으로, 의미와 동일하게 PG에서 이상 사용되지 않는 데이터를 정리해주는 역할을 한다. 쉽게 예를 들면 디스크 조각모음과 같다.

 

 PG MVCC (Multi Version Concurrency Control, 다중 버전 동시성 제어) 지원하기 때문에 데이터의 삭제, 수정이 발생하면 이상 사용하지 않는 여러 버전의 데이터가 존재한다. 만약 Vacuum 진행하지 않으면 이러한 데이터가 지속적으로 쌓여 실제 테이블 데이터 자체는 적은데 테이블의 공간을 차지하여 테이블이 지속적으로 커지는 문제가 발생한다. 그러면 당연히 불필요하거나 부적절한 인덱스가 증가하여 조회속도가 느려지고, I/O 오버헤드가 증가한다. 또한 트랜잭션 ID 겹침이나, 다중 트랜잭션 ID 겹침 상황으로 오래된 자료가 손실될 수도 있으며 이러한 현상이 지속되면 트랜잭션 ID 재활용하지 못해서 최악의 상황에는 데이터베이스가 멈추는 상황까지 발생할 있다. 이러한 여러 이유로 Vacuum 작업은 이유에 맞게 다양한 주기로, 다양한 대상으로 진행된다.

 

MVCC :
동시접근을 허용하는 데이터베이스에서 동시성을 제어하기 위해 사용하는 방법. , MVCC 모델에서 데이터에 접근하는 사용자는 접근한 시점에서의 데이터베이스의 Snapshot 읽는데, snapshot 데이터에 대한 변경이 완료될 (트랜잭션이 commit )까지 만들어진 변경사항은 다른 데이터베이스 사용자가 없다. 이러한 개념에 의해 사용자가 데이터를 업데이트하면 이전의 데이터를 덮어 씌우는게 아니라 새로운 버전의 데이터를 생성한다. 대신 이전 버전의 데이터와 비교해서 변경된 내용을 기록한다. 이렇게해서 하나의 데이터에 대해 여러 버전의 데이터가 존재하게 되고, 사용자는 마지막 버전의 데이터를 읽게 된다.

 

 

[Vacuum 하는 ]

Vacuum 실행되면 사용되지 않는 Dead Tuple (이하 데드 튜플) FSM(Free Space Map) 반환한다. 데드 튜플은 Vacuum 작업을 통해 FSM 반환되기 전까지는 자리에 새로운 데이터를 저장할 없다. 예를 들어 10 row 가지고 있는 테이블에 update 10만개를 했다면 10만개의 데드 튜플이 생기고, 다시 10만개의 업데이트를 했다면 Vacuum 실행되지 않은 상태에서는 다시 10만개의 데드 튜플이 발생한다. . 해당 테이블은 실제 데이터 10만개와, 20만개의 데드 튜플이 존재하게 된다. 이때 Vacuum 실행하면 20만개의 데드 튜플 공간을 FSM 반환하게 되며 다음 업데이트부터는 해당 공간을 재활용할 있다. 하지만 Vacuum 실행한다고 해서 이미 늘어난 테이블의 크기는 줄어들지는 않으며 해당 공간이 재활용되어 사용되므로 테이블 크기가 이상 늘어나지는 않는다. Vacuum 실행되므로써 FSM 공간반환 뿐만 아니라, 인덱스 전용 검색 성능을 향상하는데 참고하는 자료 지도 (VM, Visivility Map)정보를 갱신한다. 또한 삭제된 데이터뿐만 아니라 남아 있는 데이터에 대해서도 Frozen XID(XID 2) 변경해 주어 앞으로 XID wrap around 발생하더라도 트랜잭션 ID 겹침을 방지할 있다.

 

PG에서는 트랜잭션 ID 크기가 32bit 정수형 크기이며 하나의 서버에서 해당 크기를 넘기면 트랜잭션 ID 겹치는 현상이 발생한다.

 

 

[Vacuum 실행]

Vacuum 작업은 기본적으로 디스크 I/O 오버헤드를 유발한다. 때문에 동시에 작업하고 있는 다른 세션의 성능을 떨어뜨릴 있다. Vacuum 작업에 대한 비용은 아래 링크를 참고한다.

l  Cost-based Vacuum Delay : https://www.postgresql.kr/docs/9.4/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST

Vacuum 수동 또는 자동으로 실행될 있다. 그리고 Vacuum 실행 옵션에 따른 특징이 있다. 수동으로 실행할 경우 아래와 같은 명령으로 실행할 있다.

-- DB 전체 full vacuum
vacuum full analyze;
 
-- DB 전체 간단하게 실행
vacuum verbose analyze;
 
-- 특정 테이블만 간단하게 실행
vacuum analyze [테이블 ];
 
-- 특정 테이블만 full vacuum
vacuum full [테이블 ];

 

l  Vacuum : 데드 튜플을 FSM 반환하는 작업을 하며, 운영 환경에서도 DML (SELECT, INSERT, UPDATE, DELETE) 실행되고 있어도 동시에 사용할 있다.  하지만 DDL (ALTER TABLE) 명령은 Vacuum 작업이 실행되는 동안에는 사용할 없다.

l  Vacuum FULL : VACUUM FULL 작업은 해당 테이블의 사용할 있는 자료들만을 모아서 파일에 저장하는 방식을 이용하기 때문에 운영체제 입장에서 디스크 여유 공간을 확보할 있다. 작업 결과로 해당 테이블에 대해서 최적의 물리적 크기로 테이블이 만들어진다. 하지만 작업 테이블에 대한 베타적 잠금(Exclusive Lock) 지정하여 실행되기 때문에 어떠한 작업도 없다. (운영중인 데이터베이스에서는 사용 금지) 그리고 일반 VACUUM 작업에 비해 시간이 오래 걸린다. 또한 작업이 완료되기 전까지 작업을 있는 여유 공간이 있어야 작업을 있다.

l  Vacuum Analyze : 통계 메타데이터를 업데이트하므로 쿼리 옵티마이저가 정확한 쿼리 계획을 생성할 있어 Vacuum 명령어 실행 같이 실행하는 것이 좋다.

 

Autovacuum(자동) 내부 알고리즘으로 필요에 따라 Vacuum 자동으로 처리해 주는 것으로 수동처럼 명령어로 테이블을 정리하는 것이 아닌 테이블 혹은 DB 단위의 설정을 통해서 vacuum 진행된다. 이때 설정된 값에 따라서 데드 튜플의 증가를 얼마나 제어할지가 정해지기 때문에 Autovacuum 사용할 때에는 현재 운영중인 서버의 최적화 값을 파악하고 있어야 한다.

 

일반적인 Vacuum 전략은 주기적인 표준 Vacuum 작업을 진행하여 지속적으로 빈공간을 확보하여 디스크가 어느정도 커지지만 이상 커지지 않게 하여 최대한 Vacuum FULL 작업을 방지하는 것이다. Autovacuum 데몬이 이러한 전략으로 작업을 한다. , autovacuum 기능을 사용하되 Vacuum FULL 작업을 하지 않는 것을 기본 정책으로 설정하면 된다. 기본적으로 실시간(주기적) Vacuum(FULL Vacuum아님)실시하며, autovacuum_freeze_max_age 도달하면 강제로 Vacuum 작업을 실시하게 된다.

 

정확한 데이터베이스 사용량을 파악하지 않은 상태에서 autovacuum 기능을 끄는 것은 현명하지 않은 방법일 있다.

 

아래 쿼리는 튜플에 대한 정보를 확인한다.

SELECT
    n.nspname AS schema_name,
    c.relname AS table_name,
    pg_stat_get_live_tuples(c.oid) + pg_stat_get_dead_tuples(c.oid) as total_tuple,
    pg_stat_get_live_tuples(c.oid) AS live_tuple,
    pg_stat_get_dead_tuples(c.oid) AS dead_tupple,
    round(100*pg_stat_get_live_tuples(c.oid) / (pg_stat_get_live_tuples(c.oid) + pg_stat_get_dead_tuples(c.oid)),2) as live_tuple_rate,
    round(100*pg_stat_get_dead_tuples(c.oid) / (pg_stat_get_live_tuples(c.oid) + pg_stat_get_dead_tuples(c.oid)),2) as dead_tuple_rate,
    pg_size_pretty(pg_total_relation_size(c.oid)) as total_relation_size,
    pg_size_pretty(pg_relation_size(c.oid)) as relation_size
FROM pg_class AS c
JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace
WHERE pg_stat_get_live_tuples(c.oid) > 0
AND c.relname NOT LIKE 'pg_%'
ORDER BY dead_tupple DESC;

 

아래 쿼리는 Vacuum 통계 정보를 확인한다.

SELECT * FROM pg_stat_all_tables ORDER BY schemaname, relname;

 

Vacuum FULL 실행시 pg_class relfilenode 값이 변경된다. 아래 쿼리는 relfilenode 물리적인 파일 위치를 확인한다.

SELECT oid, pg_relation_filepath(oid), relname, relfilenode FROM pg_class LIMIT 10;

 

아래 쿼리는 현재 실행중인 Vacuum세션 정보를 확인할 있다.

SELECT
 datname,
 usename,
 pid,
 CURRENT_TIMESTAMP - xact_start AS xact_runtime,
 query
FROM
 pg_stat_activity
WHERE
 upper(query)
 LIKE '%VACUUM%'
ORDER BY
 xact_start;

 

[Autovacuum 데몬 워크플로우]

Autovacuum 데몬은 Autovacuum 실행기와 Autovacuum 작업자의 가지 다른 종류의 프로세스로 설계되어있다.

 

Autovacuum 실행기는 Autovacuum 매개변수가 on으로 설정될 postmaster 시작하는 기본 실행 프로세스이다. postmaster PostgreSQL 시스템에 대한 요청에 대한 처리 메커니즘 역할을 한다. 모든 프론트 엔드 프로그램은 시작 메시지를 postmaster에게 보내고 postmaster 메시지의 정보를 사용하여 백엔드 프로세스를 시작한다. Autovacuum 실행기 프로세스는 테이블에서 Vacuum 작업을 실행하기 위해 Autovacuum 작업자 프로세스를 시작할 적절한 시간을 결정한다.

Autovacuum 작업자는 테이블에서 vacuum 작업을 실행하는 실제 작업자 프로세스이다. 실행 프로그램에서 예약한 대로 데이터베이스에 연결하고 카탈로그 테이블을 읽고 Vacuum 작업을 실행할 테이블을 선택한다.

Autovacuum 시작 프로그램 프로세스는 데이터베이스의 테이블을 계속 모니터링하고 테이블이 Autovacuum 임계값에 도달한 Vacuum 작업에 적합한 테이블을 선택합니다. 임계값은 아래와 같은 매개변수를 기반으로 한다.

l  autovacuum_vacuum_threshold, autovacuum_analyze_threshold : 매개변수는 각각 autovacuum autoanalyzer 대해 예약할 테이블의 최소 업데이트 또는 삭제 수를 결정한다. 기본값은 50이다.

l  autovacuum_vacuum_scale_factor, autovacuum_analyze_scale_factor : 매개변수는 각각 autovacuum autoanalyzer 대해 예약할 테이블에 대해 변경이 필요한 테이블의 백분율을 결정한다. autovacuum_vacuum_scale_factor 기본값은 0.2(20%)이고 autovacuum_analyze_scale_factor 0.1(10%)이다. 테이블의 수가 너무 많지 않은 경우 기본 값을 사용해도 되지만, 많은 수의 행이 있는 테이블의 경우에는 빈번한 Vacuum 발생할 있어 적절한 값으로 조절하는 것이 좋다. 데이터베이스 내에서 테이블이 일부 존재하는 경우 구성 파일보다 테이블 수준에서 이러한 매개변수를 설정하는 것이 좋다.

 

임계값 계산은 아래 공식을 사용할 있다.

vacuum threshold = vacuum base threshold + vacuum scale factor * number of live tuples

 

l  Vacuum base threshold – autovacuum_vacuum_threshold

l  Vacuum scale factor – autovacuum_vacuum_scale_factor

l  Number of live tuples – The value of n_live_tup from pg_stat_all_tables view

 

Autovacuum 실행기는 자체적으로 Autovacuum 작업자 프로세스를 시작할 없으며 postmaster 프로세스에 의해 수행된다. 런처는 Autovacuum 공유 메모리 영역에 데이터베이스에 대한 정보를 저장하고 공유 메모리에 플래그를 설정하고 postmaster에게 신호를 보낸다. postmaster Autovacuum 작업자 프로세스를 시작한다. 새로운 작업자 프로세스는 공유 메모리에서 정보를 읽고 필요한 데이터베이스에 연결하고 Vacuum 작업을 완료한다.

postmaster 작업자 프로세스 시작에 실패하면 공유 메모리에 플래그를 설정하고 런처 프로세스에 신호를 보낸다. postmaster 신호를 읽고 실행기는 postmaster에게 신호를 전송하여 작업자 프로세스 시작을 다시 시도한다. (postmaster 작업자 프로세스를 시작하지 못하는 것은 로드 메모리 압력이 높거나 이미 실행 중인 프로세스가 너무 많기 때문일 있다).

Autovacuum 작업자 프로세스가 Vacuum 작업으로 완료되면 런처에 신호를 보낸다. 런처가 작업자로부터 신호를 받으면 런처가 깨어나Vacuum 테이블 목록이 공유 메모리에 너무 많으면 다른 작업자를 시작하려고 시도한다. 이는 다른 작업자가 해당 테이블에 대한 Vacuum 잠금을 기다리는데 차단되는 것을 방지하기 위한 것이다. 또한 다른 작업자가 방금 정리를 완료하여 공유 메모리에 이상 기록되지 않은 테이블을 Vacuum하지 않도록 테이블을 Vacuum하기 직전에 pgstats 테이블의 데이터를 다시 로드한다.

PostgreSQL 일반적인 오해는 Autovacuum 프로세스가 I/O 증가시킨다는 것이다. 따라서 많은 사람들이 Autovacuum 프로세스를 완전히 끄도록 선택한다. 이러한 행동은 데이터베이스 운영 초기 단계에서는 효과적인 솔루션처럼 보일 있지만 데이터베이스 크기가 증가하기 시작하면 데드 튜플이 차지하는 공간이 빠르게 증가하고, 테이블 디스크 공간 증가와 함께 데이터베이스 속도가 느려지기 때문에 권장하지 않는다.

 

 

[Autovacuum 장점]

통계 업데이트

PostgreSQL ANALYZE 데몬은 테이블의 통계를 수집하고 계산한다. 쿼리 플래너는 이러한 통계를 사용하여 쿼리 계획을 실행한다. 정보는 ANALYZE 데몬에 의해 계산 수집되며 이러한 통계를 사용하여 카탈로그 테이블에 저장된다. 그런 다음 쿼리 플래너는 데이터를 가져오기 위한 쿼리 계획을 만든다. 비슷한 시나리오에서 Autovacuum off 설정되어 있으면 ANALYZE 데몬이 통계를 수집하고 계산하지 않는다. 쿼리 플래너에는 테이블에 대한 정보가 없으므로 잘못된 쿼리 계획을 작성하게 되어 비용 효율적이지 않다.

 

트랜잭션 warparound 방지

앞서 설명한 것처럼 PostgreSQL 트랜잭션 ID 트랜잭션에 숫자를 할당한다. 트랜잭션 ID 숫자이기 때문에 허용되는 최대값 최소값과 같은 제한이 있다. PostgreSQL 트랜잭션 ID 대한 명확한 숫자로 4바이트 정수를 사용한다. , 4바이트로 생성할 있는 최대 트랜잭션 ID 2^32으로 (~ 4294967296) 40 개의 트랜잭션 ID 사용할 있다. 그러나 PostgreSQL 트랜잭션 ID 1에서 2^31( ~ 2147483648)에서 회전시켜 4바이트 정수로 트랜잭션을 무제한으로 처리할 있다. PostgreSQL 트랜잭션 ID 2147483648 도달하면 트랜잭션 ID 1에서 2 변경하여 2^31까지 할당 트랜잭션을 관리하고, 이후 추가 할당 트랜잭션을 트랜잭션 ID 1 할당하여 사용하는데 이렇게 트랜잭션 ID 교체하는 작업을 warparound라고 한다.

Autovacuum 페이지의 행을 방문하여 트랜잭션 ID 고정한다. 데이터베이스 트랜잭션 ID 수명이 autovacuum_freeze_max_age 도달할 때마다 PostgreSQL Autovacuum 프로세스를 즉시 시작하여 전체 데이터베이스에서 freeze작업을 수행한다.

 

 

[Autovacuum 모니터링]

Autovacuum 효과적으로 작동하는지 확인하려면 데드 튜플, 디스크 사용량, autovacuum 또는 ANALYZE 마지막으로 실행된 시간을 정기적으로 모니터링해야 한다.

 

Dead Tuple

PostgreSQL pg_stat_user_tables 뷰를 제공하는데, 뷰는 테이블(relname) 테이블에 있는 데드 로우(n_dead_tup) 대한 정보를 제공한다. 테이블, 특히 자주 업데이트되는 테이블의 데드 수를 모니터링하면 Autovacuum 프로세스가 주기적으로 제거하여 디스크 공간을 나은 성능을 위해 재사용할 있는지 확인하는 도움이 된다. 아래 쿼리를 사용하여 데드 튜플의 수와 테이블에서 마지막 Autovacuum 실행된 시간을 확인할 있다.

SELECT
relname AS TableName
,n_live_tup AS LiveTuples
,n_dead_tup AS DeadTuples
,last_autovacuum AS Autovacuum
,last_autoanalyze AS Autoanalyze
FROM pg_stat_user_tables;

 

Table Disk Usage

테이블이 사용하는 디스크 공간의 양을 추적하면 시간 경과에 따른 쿼리 성능의 변화를 분석할 있기 때문에 중요하다. 또한 Vacuum 관련된 문제를 감지하는 도움이 있다. 예를 들어 최근에 많은 데이터를 테이블에 추가했는데 테이블의 디스크 사용량이 예기치 않게 증가한 경우 해당 테이블에 vacuuming 문제가 있을 있다.

Vacuuming 오래된 행을 재사용 가능한 것으로 표시하는 도움이 되므로 VACUUM 정기적으로 실행되지 않으면 새로 추가된 데이터는 데드 튜플이 차지하는 디스크 공간을 재사용하는 대신 추가 디스크 공간을 사용한다.

 

Last autovacuum and autoanalyzer

pg_stat_user_tables 보기는 autovacuum 데몬이 테이블에서 마지막으로 실행된 시간에 대한 정보를 제공한다. autovacuum autoanalyze 사용하여 autovacuum 데몬이 효율적으로 작동하는지 추적할 있다. 아래 쿼리는 테이블에서 실행되는 last_autovacuum last_autoanalyze 대한 세부 정보를 제공한다.

SELECT relname, last_autovacuum,last_autoanalyze FROM pg_stat_user_tables;

 

Enabling log_autovacuum_min_duration

log_autovacuum_min_duration 매개변수는 Autovacuum 프로세스가 실행한 모든 작업을 기록하는 도움이 된다. Autovacuum 지정된 시간(밀리초) 동안 실행하거나 임계값 테이블 저장 매개변수를 초과하면 작업이 기록된다. 매개변수를 150밀리초로 설정하면 150밀리초 이상 실행되는 모든 Autovacuum 프로세스가 기록된다. 또한 매개변수가 -1 이외의 값으로 설정되면 충돌하는 잠금으로 인해 Autovacuum 작업을 건너뛸 경우 메시지가 기록된다. 또한 Autovacuum 프로세스의 느린 속도에 대한 자세한 정보를 제공할 있다.

 

Enabling an Amazon CloudWatch alarm

트랜잭션 warparound 대한 Amazon CloudWatch 경보를 설정할 있습니다. 자세한 내용은 아래 링크를 참고한다.

l  Implement an Early Warning System for Transaction ID Wraparound in Amazon RDS for PostgreSQL : https://aws.amazon.com/ko/blogs/database/implement-an-early-warning-system-for-transaction-id-wraparound-in-amazon-rds-for-postgresql/

또한 CloudWatch 지표를 사용하여 전체 시스템 리소스 사용량을 모니터링하고 Autovacuum 세션이 동시에 실행될 허용 가능한 범위 내에 있는지 확인할 있다.

 

 

[일반적으로 자주 겪는 Autovacuum 문제]

Autovacuum parameter tuning

Autovacuum 정기적으로 테이블의 Vacuum 프로세스를 트리거하지 않거나 효율적으로 수행되지 않는 경우 Autovacuum 매개변수 조정을 고려해야 한다. Autovacuum 프로세스는 테이블에서 VACUUM ANALYZE 명령을 자동으로 실행해야 하는 시기를 결정하기 위해 여러 구성 설정에 따라 달라진다. 아래 쿼리는 조정할 있는 Autovacuum 매개변수 목록을 제공합니다.

select category, name,setting,unit,source,min_val,max_val from pg_settings where category = 'Autovacuum' ;

 

 

Settings​​열에는 현재 구성된 값이 표시된다. boot_val열에는 기본 매개변수를 변경하지 않을 사용하는 PostgreSQL에서 설정한 Autovacuum 매개변수의 기본값이 표시된다. 이러한 Autovacuum 매개변수를 조정하면 Autovacuum 프로세스가 테이블에서 자주 효율적으로 작동한다. Autovacuum 조정에 대한 자세한 내용은 아래 링크를 참고한다.

l  A Case Study of Tuning Autovacuum in Amazon RDS for PostgreSQL : https://aws.amazon.com/ko/blogs/database/a-case-study-of-tuning-autovacuum-in-amazon-rds-for-postgresql/

 

Autovacuum skipped due to lock conflicts

테이블에서 Vacuum 실행하려면 Autovacuum 프로세스가 SHARE UPDATE EXCLUSIVE 잠금을 획득해야 하는데, 이는 트랜잭션이 동시에 SHARE UPDATE EXCLUSIVE 잠금을 보유할 없기 때문에 다른 잠금과 충돌한다. 이는 SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE ACCESS EXCLUSIVE 같은 다른 잠금 모드에서도 동일하다.

SHARE UPDATE EXCLUSIVE 잠금은 SELECT, UPDATE, INSERT 또는 DELETE 차단하지 않으며 아래 잠금이 있는 트랜잭션만 차단한다.

l  SHARE UPDATE EXCLUSIVE – Acquired by VACUUM (without FULL), ANALYZE, CREATE INDEX CONCURRENTLY, REINDEX CONCURRENTLY, CREATE STATISTICS, and certain ALTER INDEX and ALTER TABLE variants.

l  SHARE – Acquired by CREATE INDEX (without CONCURRENTLY).

l  SHARE ROW EXCLUSIVE – Acquired by CREATE TRIGGER and some forms of ALTER TABLE.

l  EXCLUSIVE – Acquired by REFRESH MATERIALIZED VIEW CONCURRENTLY.

l  ACCESS EXCLUSIVE – Acquired by DROP TABLE, TRUNCATE, REINDEX, CLUSTER, VACUUM FULL, and REFRESH MATERIALIZED VIEW (without CONCURRENTLY) commands. Many forms of ALTER INDEX and ALTER TABLE also acquire a lock at this level.

따라서 트랜잭션이 테이블에 대한 이러한 잠금 하나를 유지하라는 요청과 함께 제공되고 Autovacuum 데몬이 이미 해당 테이블 하나에서 Vacuum 작업을 실행 중인 경우, 다른 트랜잭션이 잠금을 취할 있도록 Vacuum 작업을 즉시 취소한다. 유사하게, 트랜잭션이 이미 테이블에 대한 ACCESS EXCLUSIVE 잠금을 보유하고 있는 경우 Autovacuum 해당 테이블을 Vacuuming에서 건너뛴다. Autovacuum 프로세스는 다음 반복에서 Vacuum 작업을 실행하기 위해 건너뛴 테이블을 유지한다.

 

Autovacuum action skipped due long-running transactions

PostgreSQL MVCC 개념을 기반으로 하기 때문에 하나 이상의 트랜잭션이 오래된 버전의 데이터에 액세스하는 경우 Autovacuum 프로세스는 데드 튜플을 정리하지 않는다. 데이터가 삭제되거나 업데이트되기 전에 생성된 데이터의 스냅샷에서 트랜잭션이 작업 중인 경우 Autovacuum 해당 데드 튜플을 건너뛰고 해당 데드 튜플은 다음 반복에서 Vacuum 된다. 이런 케이스는 일반적으로 데이터베이스의 장기 실행 트랜잭션에서 발생한다. 데이터베이스에서 장기 실행 트랜잭션을 찾으려면 아래 쿼리를 실행한다. 예제 쿼리는 5분이상 실행되고 있는 쿼리를 나타낸다.

SELECT now()-query_start as Running_Since, pid, datname, usename, application_name, client_addr , left(query,60) FROM pg_stat_activity WHERE state in ('active','idle in transaction') AND (now() - query_start) > interval '5 minutes';

 

Autovacuum 데드 튜플을 건너뛰게 있으므로 모니터링의 일부로 트랜잭션 세션의 유휴 상태(idle in transaction) 포함하는 것이 좋다.

 

 

[Autovacuum 모범 사례]

Allocating memory for autovacuum

maintenance_work_mem 파라미터는 Autovacuum 성능에 영향을 미치는 중요한 파라미터이다. Autovacuum 프로세스가 데이터베이스의 테이블을 스캔하는 사용할 메모리 양을 결정하고 Vacuum 필요한 ID 보유한다.

매개변수를 낮게 설정하면 Vacuum 프로세스가 테이블을 여러 스캔하여 Vacuum 작업을 완료하므로 데이터베이스 성능에 부정적인 영향을 미친다.

작은 테이블이 많은 경우 autovacuum_max_workers 많이 할당하고 maintenance_work_mem 적게 할당한다. 테이블(100GB 이상) 있는 경우 많은 메모리와 적은 수의 작업자 프로세스를 할당한다. 가장 테이블에서 성공하려면 충분한 메모리가 할당되어야 한다. autovacuum_max_workers 할당한 메모리를 사용할 있다. 따라서 작업자 프로세스와 메모리의 조합이 할당하려는 메모리와 동일한지 확인해야 한다.

 

인스턴스의 경우 maintenance_work_mem 1GB 이상으로 설정하면 많은 수의 데드 튜플이 있는 테이블을 Vacuuming하는 성능이 크게 향상된다. 그러나 Vacuum 메모리 사용을 1GB 제한하는 것이 좋다. 패스에서 1 7,900 개의 데드 튜플을 처리하기에 충분하다. 그보다 많은 데드 튜플이 있는 테이블을 Vacuuming하려면 테이블 인덱스를 여러 통과해야 하므로 Vacuum 훨씬 오래 걸릴 있다. maintenance_work_mem 바이트를 6으로 나누어 단일 패스에서 Vacuum 처리할 있는 데드 튜플 수를 계산할 있다.

autovacuum_work_mem 또는 maintenance_work_mem 매개변수를 설정하면 Autovacuum 작업자 프로세스가 사용해야 하는 최대 메모리 크기가 설정된다. 기본적으로 autovacuum_work_mem -1 설정되며 이는 Autovacuum 작업자 프로세스에 대한 메모리 할당이 maintenance_work_mem 설정을 사용해야 함을 나타낸다.

 

Amazon RDS 파라미터의 기본값은 아래와 같이 계산된 KB 적용되어 있다.

GREATEST({DBInstanceClassMemory/63963136*1024},65536).

 

자세한 내용은 아래 링크를 참고한다.

l  Common DBA tasks for Amazon RDS for PostgreSQL : https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.WorkMemory

l  A Case Study of Tuning Autovacuum in Amazon RDS for PostgreSQL : https://aws.amazon.com/ko/blogs/database/a-case-study-of-tuning-autovacuum-in-amazon-rds-for-postgresql/

 

Reducing the chances of transaction ID wraparound

일부 사용 사례에서는 조정된 Autovacuum 설정도 트랜잭션 ID warparound 방지할 만큼 공격적이지 않다. 문제를 해결하기 위해 Amazon RDS에는 autovacuum 파라미터 값을 자동으로 조정하는 메커니즘이 있다. 적응형 Autovacuum 파라미터 조정이 활성화된 경우 Amazon RDS CloudWatch 지표 MaximumUsedTransactionIDs 750,000,000 또는 autovacuum_freeze_max_age 값에 도달할 Autovacuum 파라미터 조정을 시작한다.

Amazon RDS 테이블이 계속해서 트랜잭션 ID warparound 향하는 경향이 있을 Autovacuum 대한 매개변수를 계속 조정한다. 조정은 warparound 피하기 위해 Autovacuum 많은 리소스를 할당한다. Amazon RDS 다음과 같은 Autovacuum 관련 파라미터를 업데이트한다.

l  autovacuum_vacuum_cost_delay autovacuum 프로세스가 제한을 초과할 대기하는 지정된 시간(밀리초)이다. 기본값은 20밀리초이다.

l  autovacuum_vacuum_cost_limit Autovacuum 프로세스를 휴면 상태로 만드는 누적 비용으로 기본값은 200이다.

l  autovacuum_work_mem Autovacuum 작업자 프로세스에서 사용하는 최대 메모리 양이다. 기본값은 -1 maintenance_work_mem 값을 사용해야 함을 나타낸다.

l  autovacuum_naptime 주어진 데이터베이스에서 Autovacuum 실행 사이의 최소 지연을 지정한다. 라운드에서 데몬은 데이터베이스를 검사하고 해당 데이터베이스의 테이블에 대해 필요에 따라 VACUUM ANALYZE 명령을 실행한다. 지연은 단위로 측정되며 기본값은 1분이다. 매개변수는 postgresql.conf 파일이나 서버 명령줄에서만 설정할 있다.

 

Amazon RDS 기존 값이 충분히 공격적이지 않은 경우에만 이러한 파라미터를 수정한다. 이러한 파라미터는 DB 인스턴스의 메모리에서 수정되며 파라미터 그룹에서는 변경되지 않는다. Amazon RDS 이러한 Autovacuum 파라미터를 수정할 때마다 Amazon RDS API 통해 AWS Management 콘솔에서 있는 영향을 받는 DB 인스턴스에 대한 이벤트를 생성한다. MaximumUsedTransactionIDs CloudWatch 지표가 임계값 아래로 반환되면 Amazon RDS 메모리의 Autovacuum 관련 파라미터를 파라미터 그룹에 지정된 값으로 재설정한다.

 

Setting autovacuum at table level

글로벌 Autovacuum 설정을 기반으로 증가하는 PostgreSQL 환경에서 테이블은 효과적으로 Vacuum되지 않고 작은 테이블은 자주 Vacuum되는 것을 있다. 이러한 시나리오를 피하기 위해 다음 단계에 따라 테이블 수준에서 Autovacuum 매개변수를 설정할 있다.

1.        데이터베이스에서 테이블을 나열한다.

2.        많은 수의 변경 사항이 발생한 테이블을 나열한다.

3.        어떤 테이블에 'n_dead_tup' 수가 많은지 확인한다.

4.        테이블이 마지막으로 자동 분석 자동 진공 처리된 시간을 확인한다.

5.        테이블 수준에서 Autovacuum Autoanalyze 매개변수를 변경한다.

 

 

[참고자료]

l  Amazon Aurora : https://aws.amazon.com/ko/rds/aurora/

l  정기적인 Vacuum 작업 : https://www.postgresql.kr/docs/9.4/routine-vacuuming.html

l  MVCC : https://en.wikipedia.org/wiki/Multiversion_concurrency_control

l  Free Space Map(FSM) : https://www.postgresql.org/docs/current/storage-fsm.html

l  Visibility Map (VM) : https://www.postgresql.org/docs/current/storage-vm.html

l  Understanding autovacuum in Amazon RDS for PostgreSQL environments : https://aws.amazon.com/ko/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/

l  AWS RDS for PostgreSQL Vacuum Tuning : https://catalog.us-east-1.prod.workshops.aws/workshops/2a5fc82d-2b5f-4105-83c2-91a1b4d7abfe/en-US/3-intermediate/vacuum-tuning

l  Visibility Map Problems : https://wiki.postgresql.org/wiki/Visibility_Map_Problems

l  Cost-based Vacuum Delay : https://www.postgresql.kr/docs/9.4/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST

l  Automatic Vacuuming : https://www.postgresql.org/docs/current/runtime-config-autovacuum.html

l  Implement an Early Warning System for Transaction ID Wraparound in Amazon RDS for PostgreSQL : https://aws.amazon.com/ko/blogs/database/implement-an-early-warning-system-for-transaction-id-wraparound-in-amazon-rds-for-postgresql/

l  A Case Study of Tuning Autovacuum in Amazon RDS for PostgreSQL : https://aws.amazon.com/ko/blogs/database/a-case-study-of-tuning-autovacuum-in-amazon-rds-for-postgresql/

l  Common DBA tasks for Amazon RDS for PostgreSQL : https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.WorkMemory

 

 

 

 

2022-10-26 / Sungwook Kang / http://sungwookkang.com

 

 

AWS, Aurora, PostgreSQL, Autovacuunm, Vacuum

[AWS Aurora] Aurora Parallel Query 활성화 방법 특징

 

l  Version : AWS Aurora

 

Amazon Aurora MySQL 병렬 쿼리는 데이터 집약적인 쿼리 처리에 수반되는 I/O 컴퓨팅의 일부를 병렬화 하는 최적화 작업이다. 병렬화되는 작업은 스토리지로부터 검색, 추출, 어떤 행이 WHERE JOIN절의 조건과 일치하는지 판단한다. 데이터 집약적인 작업은 Aurora 분산 스토리지 계층의 여러 노드에 위임(푸시다운)되고 병렬 쿼리가 없으면 쿼리가 스캔한 모든 데이터를 Aurora MySQL 클러스터(헤드노드)내의 단일 노드로 가져오고 거기에서 모든 쿼리 처리를 수행한다. 병렬 쿼리 기능을 설정하면 Aurora MySQL 엔진이 힌트 또는 테이블 속성과 같은 SQL 변경 필요 없이 쿼리에 따라 자동으로 병렬화 여부를 판단한다.

 

데이터베이스를 생성할 [Engine Version]에서 [Hide filters] 확장하여 parallel query 기능을 활성화할 있다.

 

기본적으로, 병렬 쿼리를 사용하지 않을 경우 Aurora 쿼리에 대한 처리는 원시 데이터를 Aurora 클러스터 단일 노드(헤드 노드) 전송한다. 그런 다음 Aurora 해당 단일 노드의 단일 스레드에서 해당 쿼리에 대해 추가되는 모든 처리를 수행한다. 병렬 쿼리를 사용할 경우, 이러한 I/O 집약적이고 CPU 집약적인 작업의 대부분이 스토리지 계층의 노드로 위임된다. 행은 이미 필터링되고 값은 이미 추출되어 전송된 상태로, 결과 집합의 간소화된 행만 다시 헤드 노드로 전송된다. 성능 혜택은 네트워크 트래픽의 감소, 헤드 노드에서 CPU 사용량의 감소, 스토리지 노드 전체에서 I/O 병렬화로부터 비롯된다. 병렬 I/O, 필터링 프로젝션의 양은 쿼리를 실행하는 Aurora 클러스터의 DB 인스턴스 수와 무관하다.

 

 

아래는 위에서 설명한 병렬 쿼리 사용의 장점을 목록으로 정리한 것이다.

l  여러 스토리 노드에 걸친 물리적 읽기 요청을 병렬화 하여 I/O 성능 개선

l  네트워크 트래픽 감소 : Aurora 전체 데이터 페이지를 스토리지 노드로부터 헤드 노드로 전송한 다음 후에 불필요한 행과 열을 필터링 하지 않고 결과 집합에 필요한 값만 포함된 간소화된 튜플을 전송한다.

l  푸시 다운, 필터링 WHERE 절에 대한 프로젝션으로 인한 헤드 노드에 대한 CPU 사용량 감소.

l  버퍼 풀에서의 메모리 압력 감소 : 병렬 쿼리에 의해 처리된 페이지는 버퍼풀에 추가되지 않으므로 데이터 집약적인 스캔 버퍼 풀에서 자주 사용되는 데이터가 제거될 가능성이 감소.

l  기존 데이터에 대한 장기 실행 분석 쿼리 수행이 유용해진 덕분에 추출, 변환, 로드(ETL) 파이프라인에서 데이터 중복의 잠재적 감소.

 

*주의*
Aurora MySQL 병렬 쿼리의 아키텍처는 다른 데이터베이스 시스템에서 이름이 유사한 기능의 아키텍처와 다르다. Aurora MySQL 병렬 쿼리는 SMP(Symmetric Multi Processing) 포함하지 않아, 데이터베이스의 CPU 용량에 의존하지 않는다. 병렬 처리는 쿼리 조정자 역할을 하는 Aurora MySQL 서버와는 독립적인 스토리지 계층에서 일어난다.

 

Aurora MySQL에서 병렬 쿼리를 사용하기 위해서는 가지 사전 조건 제한 사항이 있다. 해당 내용은 버전에 따라 지원되는 내용이 다르고, 향후 버전 업데이트에 따라 변경될 가능성이 크기 때문에 자세한 내용은 아래 링크의 내용을 직접 참고한다.

l  Amazon Parallel Query  : https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/AuroraUserGuide/aurora-mysql-parallel-query.html

 

Aurora MySQL 3 버전 부터는 해시조인(Hash Join) 기본적으로 설정되어 있다. optimizer_switch 구성 설정의 block_nested_loop 플래그를 사용하여 설정을 비활성화 있다. Aurora MySQL 3버전에서는 Aurora_disable_hash_join 옵션은 사용되지 않는다.

 

Aurora MySQL 1.23 또는 2.09 이상 버전에서는 병렬 쿼리 해시 조인 설정이 기본적으로 해제되어 있다. 부분을 활성화하기 위해서는 클러스터 구성 파라메터 aurora_disable_hash_join=OFF 설정한다.

 

버전 1.23 이전의 Aurora MySQL 5.6 호환 클러스터의 경우 해시 조인은 병렬 쿼리 클러스터에서 항상 사용할 있다. 경우 해시 조인 기능에 대해 어떤 작업도 수행할 필요가 없다. 이러한 클러스터를 버전 1 또는 버전 2 상위 릴리스로 업그레이드하는 경우 해시 조인도 설정해야 한다.

 

병렬 쿼리를 사용하려면 테이블 속성이 ROW_FORMAT=Compact 또는 ROW_FORMAT=Dynammic 설정을 사용해야하기 때문에 INNODB_FILE_FORMAT 구성 옵션에 대한 변경 사항이 있는지 확인해야한다. 옵션을 변경할 때에는 항상 변경 전후에 대한 성능 문제가 발생할 있으므로 반드시 워크로드 테스트를 진행할 있도록 한다.

 

앞에서도 언급하였지만 병렬 쿼리를 이용하기 위해 어떤 특별한 조치를 수행할 필요는 없다. 필수적 요구사항을 충족한 후에는 쿼리 옵티마이저가 특정 쿼리에 대하여 병렬 쿼리를 사용할지 여부를 자동으로 결정하기 때문이다. 쿼리가 실행될 병렬 쿼리로 실행되었는지 유무는 EXPLAIN 명령을 실행하여 실행계획을 통해 확인할 있다.

아래 예시는 해시 조인이 설정되어 있지만 병렬 쿼리가 해제되어 있어 병렬 쿼리가 아닌 해시 조인으로 실행계획이 표시되었다.

 

병렬 쿼리가 설정된 후에는 해시 조인 실행 parallel query 라고 표시된 것을 확인할 있다.

 

Aurora MySQL 클러스터가 병렬 쿼리를 실행할 버퍼풀을 사용하지 않기 때문에 VolumeReadIOPS 값이 증가할 있다. 따라서 쿼리는 빠르기 실행되지만 이렇게 최적화된 프로세싱은 읽기 작업 관련 비용을 증가시킬 있다. 병렬 쿼리 모니터링에 대한 카운터는 아래 링크에서 병렬 쿼리 모니터링섹션을 참고할 있도록 한다. 카운터는 DB 인스턴스 수준에서 추적된다. 서로 다른 엔드포인트로 연결된 경우 DB 인스턴스가 자체의 고유한 병렬 쿼리 집합을 실행하기 때문에 사로 다른 지표가 표시될 수도 있다. 또한 리더 엔드포인트가 세션마다 서로 다른 DB 인스턴스에 연결된 경우에도 서로 다른 지표가 표시될 수도 있다.

l  Amazon Parallel Query  : https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/AuroraUserGuide/aurora-mysql-parallel-query.html

 

병렬 쿼리는 InnoDB 테이블에만 적용된다. Aurora MySQL에서는 임시 테이블 사용시, 임시 저장소로 MyISAM 사용하기 때문에 임시 테이블을 포함하는 내부 쿼리 단계에서는 병렬쿼리를 사용하지 않는다. 그리고 실행 계획으로는 Using temporary라고 표시된다.

(MySQL 8.0 부터는 임시 테이블이 디스크에 저장될 InnoDB 스토리지를 사용하도록 개선되어 있다.)

 

 

[참고자료]

l  Amazon Parallel Query  : https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/AuroraUserGuide/aurora-mysql-parallel-query.html

l  https://aws.amazon.com/blogs/aws/new-parallel-query-for-amazon-aurora/

 

 

2022-07-25 / Sungwook Kang / http://sungwookkang.com

 

 

AWS, Aurora, Aurora Parallel Query, 오로라 병렬처리, 병렬 쿼리, Aurora Optimize, 오로라 최적화

+ Recent posts