Hive ACID 트랜잭션
Hive ACID 트랜잭션 (Hive Transactions)
Hive의 ACID 트랜잭션은 행(row) 단위의 완전한 ACID 의미론을 제공해서, 한 애플리케이션이 행을 추가하는 동안 다른 애플리케이션이 같은 파티션을 읽어도 서로 간섭하지 않게 해줘요. Hive 0.14부터 INSERT...VALUES, UPDATE, DELETE가 추가됐고, ORC + 버킷 테이블 + DbTxnManager 구성을 기반으로 동작한답니다.
출처: 문서
본문
Hive 3+로 업그레이드 (Upgrade to Hive 3+)
Hive 3 이전 버전이 만든 모든 transactional 테이블은 3.0으로 업그레이드하기 전에 모든 파티션에 대해 Major Compaction을 실행해야 해요. 더 정확히는, 마지막 Major Compaction 이후 update/delete/merge 문이 실행된 파티션은 또 다른 Major Compaction을 거쳐야 해요. Hive가 Hive 3으로 업그레이드될 때까지 이 파티션에서는 더 이상 update/delete/merge가 일어나면 안 돼요.
ACID란 무엇이며 왜 사용해야 하는가? (What is ACID and why should you use it?)
ACID는 데이터베이스 트랜잭션의 네 가지 특성을 나타내요: 원자성(Atomicity, 연산이 완전히 성공하거나 실패하며 부분 데이터를 남기지 않음), 일관성(Consistency, 애플리케이션이 연산을 수행하면 그 결과가 이후 모든 연산에서 보임), 격리성(Isolation, 한 사용자의 불완전한 연산이 다른 사용자에게 예상치 못한 부작용을 일으키지 않음), 지속성(Durability, 연산이 완료되면 머신이나 시스템 장애에도 보존됨). 이러한 특성은 데이터베이스 시스템의 트랜잭션 기능의 일부로 오랫동안 기대되어 왔어요.
Hive 0.13까지는 원자성, 일관성, 지속성이 파티션 수준에서 제공됐어요. 격리성은 사용 가능한 락 메커니즘(ZooKeeper 또는 in-memory) 중 하나를 켜서 제공할 수 있었죠. Hive 0.13에서 트랜잭션이 추가되면서 이제 행 수준의 완전한 ACID 의미론을 제공할 수 있게 됐어요. 그래서 한 애플리케이션이 행을 추가하는 동안 다른 애플리케이션이 같은 파티션에서 읽어도 서로 간섭하지 않아요.
ACID 의미론을 가진 트랜잭션은 다음 사용 사례를 해결하기 위해 Hive에 추가됐어요:
- 데이터의 스트리밍 수집(streaming ingest). 많은 사용자가 Apache Flume, Apache Storm, Apache Kafka 같은 도구로 데이터를 Hadoop 클러스터로 스트리밍해요. 이 도구들은 초당 수백 행 이상의 속도로 데이터를 쓸 수 있지만, Hive는 15분에서 1시간마다 한 번씩만 파티션을 추가할 수 있어요. 파티션을 더 자주 추가하면 테이블에 파티션 수가 압도적으로 늘어나요. 이 도구들은 기존 파티션으로 스트리밍할 수 있지만, 그러면 읽는 쪽에서 dirty read(쿼리를 시작한 뒤에 쓰인 데이터를 보는 것)를 하게 되고, 디렉토리에 많은 작은 파일이 남아 NameNode에 부담이 가고 있어요. 이 새 기능으로 이 사용 사례를 지원하면서도 읽는 쪽이 일관된 데이터 뷰를 얻고 파일이 너무 많이 생기지 않게 해줘요.
- 천천히 변하는 차원(Slow changing dimensions). 전형적인 스타 스키마 데이터 웨어하우스에서 차원 테이블은 시간이 지나면서 천천히 변해요. 예를 들어 소매업자가 새 매장을 열면 stores 테이블에 추가해야 하고, 기존 매장의 평방 피트나 다른 추적 특성이 바뀔 수도 있어요. 이러한 변경은 개별 레코드의 삽입 또는 레코드의 갱신(선택한 전략에 따라)으로 이어져요. Hive는 0.14부터 이를 지원할 수 있어요.
- 데이터 재작성(Data restatement). 수집한 데이터가 부정확하다는 것을 발견해 수정해야 하는 경우가 있어요. 또는 데이터의 첫 인스턴스가 근사치(90%의 서버 보고)이고 나중에 전체 데이터가 제공될 수 있어요. 또는 비즈니스 규칙이 후속 트랜잭션 때문에 특정 트랜잭션을 재작성해야 할 수 있어요(예: 구매 후 고객이 멤버십을 구매해 이전 구매를 포함해 할인 가격을 받을 자격을 얻는 경우). 또는 사용자가 계약상 관계 종료 시 고객 데이터를 제거해야 할 수 있어요. Hive 0.14부터 이러한 사용 사례는 INSERT, UPDATE, *DELETE*로 지원될 수 있어요.
- SQL MERGE 문을 사용한 대량 갱신(Bulk updates).
제약 사항 (Limitations)
- BEGIN, COMMIT, ROLLBACK은 아직 지원되지 않아요. 모든 언어 연산은 자동 커밋(autocommit)이에요. 이들은 향후 릴리스에서 지원할 계획이에요.
- 이 첫 릴리스에서는 ORC 파일 포맷만 지원돼요. 이 기능은 업데이트나 삭제가 기본 레코드에 어떻게 적용되는지 판단할 수 있는(기본적으로 명시적 또는 암시적 행 id가 있는) 모든 저장 포맷에서 트랜잭션을 사용할 수 있도록 설계됐지만, 지금까지 통합 작업은 ORC에 대해서만 이루어졌어요.
- 기본적으로 트랜잭션은 꺼져 있도록 구성돼요. 구성하려면 아래 Configuration 섹션을 참고해요.
- 이 기능들을 사용하려면 테이블이 버킷화(bucketed)되어야 해요. 트랜잭션과 ACID를 사용하지 않는 같은 시스템의 테이블은 버킷화할 필요가 없어요. 외부 테이블은 변경 사항이 컴팩터의 통제를 벗어나므로 ACID 테이블로 만들 수 없어요(HIVE-13175).
- non-ACID 세션에서 ACID 테이블을 읽고 쓰는 것은 허용되지 않아요. 즉, ACID 테이블을 사용하려면 Hive 트랜잭션 매니저가
org.apache.hadoop.hive.ql.lockmgr.DbTxnManager로 설정되어야 해요. - 현재는 스냅샷 수준 격리(snapshot level isolation)만 지원돼요. 주어진 쿼리가 시작되면 일관된 데이터 스냅샷이 제공돼요. dirty read, read committed, repeatable read, serializable은 지원되지 않아요. BEGIN이 도입되면서 단일 쿼리보다는 트랜잭션 기간 동안 스냅샷 격리를 지원하려는 의도예요. 다른 격리 수준은 사용자 요청에 따라 추가될 수 있어요.
- 기존 ZooKeeper와 in-memory 락 매니저는 트랜잭션과 호환되지 않아요. 이 문제를 해결할 의도는 없어요. 트랜잭션에 대한 락이 저장되는 방식에 대한 논의는 Basic Design을 참고해요.
ACID 테이블에 대한 ALTER TABLE을 사용한 스키마 변경은 지원되지 않아요. HIVE-11421이 추적 중이에요.1.3.0/2.0.0에서 수정됨.- Metastore DB로 Oracle을 사용하고 "datanucleus.connectionPoolingType=BONECP"이면 간헐적으로 "No such lock.." 및 "No such transaction..." 오류가 발생할 수 있어요. 이 경우 "datanucleus.connectionPoolingType=DBCP"로 설정하는 것을 권장해요.
- LOAD DATA... 문은 transactional 테이블에서 지원되지 않아요. (이것은 HIVE-16732까지 제대로 강제되지 않았어요.)
스트리밍 API (Streaming APIs)
Hive는 데이터 스트리밍 수집과 스트리밍 변경(mutation)을 위한 API를 제공해요:
- Hive HCatalog Streaming API
- Hive Streaming API (Hive 3부터)
- HCatalog Streaming Mutation API (Hive 2.0.0 이상에서 사용 가능)
이 두 API의 비교는 Streaming Mutation 문서의 Background 섹션에서 볼 수 있어요.
문법 변경 (Grammar Changes)
INSERT...VALUES, UPDATE, DELETE는 Hive 0.14부터 SQL 문법에 추가됐어요. 자세한 내용은 LanguageManual DML을 참고해요.
ACID와 트랜잭션을 지원하기 위해 Hive의 DDL에 몇 가지 새 명령이 추가되고, 일부 기존 DDL이 수정됐어요.
SHOW TRANSACTIONS라는 새 명령이 추가됐어요. 자세한 내용은 Show Transactions를 참고해요.
SHOW COMPACTIONS라는 새 명령이 추가됐어요. 자세한 내용은 Show Compactions를 참고해요.
SHOW LOCKS 명령은 트랜잭션과 연관된 새 락에 대한 정보를 제공하도록 변경됐어요. ZooKeeper 또는 in-memory 락 매니저를 사용 중이라면 이 명령 출력의 차이를 느끼지 못할 거예요. 자세한 내용은 Show Locks를 참고해요.
테이블 또는 파티션의 컴팩션을 요청하는 ALTER TABLE 옵션이 추가됐어요. 일반적으로 사용자가 컴팩션을 요청할 필요는 없는데, 시스템이 필요를 감지해 컴팩션을 시작하기 때문이에요. 그러나 테이블에 대해 컴팩션이 꺼져 있고 사용자가 시스템이 선택하지 않는 시간에 컴팩션하고 싶다면 ALTER TABLE로 컴팩션을 시작할 수 있어요. 자세한 내용은 Alter Table/Partition Compact를 참고해요. 이는 컴팩션 요청을 큐에 넣고 반환해요. 컴팩션 진행 상황을 보려면 SHOW COMPACTIONS를 사용하면 돼요.
ABORT TRANSACTIONS라는 새 명령이 추가됐어요. 자세한 내용은 Abort Transactions을 참고해요.
기본 설계 (Basic Design)
HDFS는 파일의 제자리(in-place) 변경을 지원하지 않아요. 또한 사용자가 읽고 있는 파일에 작성자가 추가하는 상황에서 읽기 일관성도 제공하지 않아요. HDFS 위에서 이러한 기능을 제공하기 위해 다른 데이터 웨어하우징 도구에서 쓰는 표준 접근 방식을 따랐어요. 테이블 또는 파티션의 데이터는 일련의 base 파일에 저장돼요. 새 레코드, 갱신, 삭제는 delta 파일에 저장돼요. 테이블이나 파티션을 변경하는 각 트랜잭션(또는 Flume과 Storm 같은 스트리밍 에이전트의 경우 각 트랜잭션 배치)에 대해 새 delta 파일 집합이 생성돼요. 읽을 때 리더는 base와 delta 파일을 병합하고, 읽으면서 갱신과 삭제를 적용해요.
Base 및 Delta 디렉토리
이전에는 파티션(또는 파티션되지 않은 테이블이면 테이블)의 모든 파일이 단일 디렉토리에 있었어요. 이러한 변경으로, ACID 인식 작성자로 쓰여진 파티션(또는 테이블)은 base 파일용 디렉토리와 각 delta 파일 집합용 디렉토리를 갖게 돼요. 파티션되지 않은 테이블 "t"의 모습은 다음과 같아요:
테이블 "t"의 파일 시스템 레이아웃
hive> dfs -ls -R /user/hive/warehouse/t;
drwxr-xr-x - ekoifman staff 0 2016-06-09 17:03 /user/hive/warehouse/t/base_0000022
-rw-r--r-- 1 ekoifman staff 602 2016-06-09 17:03 /user/hive/warehouse/t/base_0000022/bucket_00000
drwxr-xr-x - ekoifman staff 0 2016-06-09 17:06 /user/hive/warehouse/t/delta_0000023_0000023_0000
-rw-r--r-- 1 ekoifman staff 611 2016-06-09 17:06 /user/hive/warehouse/t/delta_0000023_0000023_0000/bucket_00000
drwxr-xr-x - ekoifman staff 0 2016-06-09 17:07 /user/hive/warehouse/t/delta_0000024_0000024_0000
-rw-r--r-- 1 ekoifman staff 610 2016-06-09 17:07 /user/hive/warehouse/t/delta_0000024_0000024_0000/bucket_00000
컴팩터 (Compactor)
컴팩터는 ACID 시스템을 지원하기 위해 Metastore 내부에서 실행되는 일련의 백그라운드 프로세스예요. Initiator, Worker, Cleaner, AcidHouseKeeperService 및 기타 몇 가지로 구성돼요.
Delta 파일 컴팩션
연산이 테이블을 수정할수록 delta 파일이 더 많이 생성되고, 적절한 성능을 유지하기 위해 컴팩션해야 해요. minor, major, rebalance 세 가지 유형의 컴팩션이 있어요.
- Minor compaction은 기존 delta 파일 집합을 가져와 버킷당 단일 delta 파일로 다시 써요.
- Major compaction은 하나 이상의 delta 파일과 버킷의 base 파일을 가져와 버킷당 새 base 파일로 다시 써요. Major compaction은 더 비싸지만 더 효과적이에요.
- rebalance compaction에 대한 자세한 내용은 여기에서 볼 수 있어요: Rebalance compaction
모든 컴팩션은 백그라운드에서 수행돼요. Minor와 major 컴팩션은 데이터의 동시 읽기/쓰기를 막지 않아요. Rebalance compaction은 배타적 쓰기 락을 사용하므로 동시 쓰기를 막아요. 컴팩션 후 시스템은 이전 파일의 모든 리더가 끝날 때까지 기다린 다음 이전 파일을 제거해요.
Initiator
이 모듈은 어떤 테이블이나 파티션이 컴팩션 대상인지 발견하는 역할을 해요. [hive.compactor.initiator.on](#hive-compactor-initiator-on)을 사용해 Metastore에서 활성화해야 해요. 아래 "New Configuration Parameters for Transactions" 테이블에는 컴팩션 태스크가 생성되는 시점과 어떤 유형의 컴팩션이 수행되는지 제어하는 *.threshold 형태의 속성이 여러 개 있어요. 각 컴팩션 태스크는 1개 파티션(또는 테이블이 파티션되지 않았다면 전체 테이블)을 처리해요. 주어진 파티션에 대한 연속 컴팩션 실패 횟수가 hive.compactor.initiator.failed.compacts.threshold를 초과하면 이 파티션에 대한 자동 컴팩션 스케줄링이 중지돼요. 자세한 내용은 Configuration Parameters 테이블을 참고해요.
Worker
각 Worker는 단일 컴팩션 태스크를 처리해요. 컴팩션은 <hostname>-compactor-<db>.<table>.<partition> 형태의 이름을 가진 MapReduce 잡이에요. 각 worker는 정의된 경우 hive.compactor.job.queue를 통해 잡을 클러스터에 제출하고 잡이 끝나길 기다려요. hive.compactor.worker.threads는 각 Metastore의 Worker 수를 결정해요. Hive 웨어하우스의 총 Worker 수가 최대 동시 컴팩션 수를 결정해요.
Cleaner
이 프로세스는 컴팩션 후 delta 파일이 더 이상 필요 없다고 판단되면 삭제하는 프로세스예요.
AcidHouseKeeperService
이 프로세스는 hive.txn.timeout 시간 동안 하트비트하지 않은 트랜잭션을 찾아 중단(abort)시켜요. 시스템은 트랜잭션을 시작한 클라이언트가 하트비트를 중단했다면 충돌했고, 잠긴 리소스가 해제되어야 한다고 가정해요.
SHOW COMPACTIONS
이 명령은 현재 실행 중인 컴팩션과 최근 이력(구성 가능한 보존 기간)에 대한 정보를 표시해요. 이 이력 표시는 HIVE-12353부터 사용할 수 있어요.
이 명령의 출력에 대한 자세한 내용은 LanguageManual DDL#ShowCompactions를, 이 명령의 출력에 영향을 주는 구성 속성은 NewConfigurationParametersforTransactions/Compaction History를 참고해요. 시스템은 유형별(failed, succeeded, attempted) 마지막 N개 항목을 보존해요(N은 유형별로 구성 가능).
트랜잭션/락 매니저
이전의 "database/table/partition lock manager"(hive.lock.manager, 기본 org.apache.hadoop.hive.ql.lockmgr.zookeeper.ZooKeeperHiveLockManager) 개념을 통합한 "transaction manager"라는 새 논리 엔티티가 추가됐어요. 트랜잭션 매니저는 이제 트랜잭션 락 관리도 담당해요. 기본 DummyTxnManager는 예전 Hive 버전의 동작을 모방해요: 트랜잭션이 없고 hive.lock.manager 속성을 사용해 테이블/파티션/데이터베이스용 락 매니저를 만들어요. 새로 추가된 DbTxnManager는 DbLockManager로 Hive metastore에서 모든 락/트랜잭션을 관리해요(트랜잭션과 락은 서버 실패에도 지속됨). 즉 트랜잭션이 활성화되면 ZooKeeper에서의 이전 락킹 동작은 더 이상 존재하지 않아요. 클라이언트가 죽어 트랜잭션이나 락이 매달리는 것을 방지하기 위해, 락 보유자와 트랜잭션 시작자는 정기적으로 metastore에 하트비트를 보내요. 구성된 시간 동안 하트비트를 받지 못하면 락이나 트랜잭션은 중단돼요.
Hive 1.3.0부터 DbLockManager가 락을 획득하려 시도하는 시간은 [hive.lock.numretires](http://Configuration Properties#hive.lock.numretires)와 [hive.lock.sleep.between.retries](http://Configuration Properties#hive.lock.sleep.between.retries)로 제어할 수 있어요. DbLockManager가 락을 획득할 수 없으면(경쟁 락의 존재 때문에) 백오프 후 일정 시간 후 다시 시도해요. 짧게 실행되는 쿼리를 지원하면서 동시에 metastore에 과부하를 주지 않기 위해 DbLockManager는 재시도 후마다 대기 시간을 두 배로 늘려요. 초기 백오프 시간은 100ms이고 hive.lock.sleep.between.retries로 상한이 정해져요. hive.lock.numretries는 주어진 락 요청을 재시도하는 총 횟수예요. 따라서 락 획득 호출이 블록되는 총 시간(100회 재시도, 60s 수면 값)은 (100ms + 200ms + 400ms + ... + 51200ms + 60s + 60s + ... + 60s) = 91m:42s:300ms예요.
이 락 매니저가 사용하는 락에 대한 자세한 내용은 여기에서 볼 수 있어요.
DbTxnManager가 사용하는 락 매니저는 "transactional=true" 속성이 없는 테이블을 포함해 모든 테이블에서 락을 획득한다는 점에 유의해요. 기본적으로 non-transactional 테이블에 대한 Insert는 배타적 락을 획득해 다른 insert와 read를 막아요. 기술적으로는 정확하지만, 이는 Hive가 전통적으로 동작한 방식(즉 락 매니저 없이)과의 이탈이에요. 하위 호환성을 위해 [hive.txn.strict.locking.mode](http://Configuration Properties#hive.txn.strict.locking.mode)(아래 테이블 참고)가 제공되며, 이는 non-transactional 테이블의 insert 작업에 공유 락을 획득하게 해요. 이는 읽히는 동안 테이블 drop을 방지하는 것 같은 락 매니저의 이점을 제공하면서도 이전 의미론을 복원해요. transactional 테이블의 경우 insert는 항상 share lock을 획득하는데, 이 테이블들은 저장 계층에서 MVCC 아키텍처를 구현해 동시 수정 작업이 있더라도 강한 읽기 일관성(Snapshot Isolation)을 제공할 수 있기 때문이에요.
설정 (Configuration)
최소한 다음 구성 매개변수를 적절히 설정해야 Hive에서 트랜잭션 지원을 켤 수 있어요:
Client Side
- hive.support.concurrency - true
- hive.enforce.bucketing - true (Hive 2.0부터 필수 아님)
- hive.exec.dynamic.partition.mode - nonstrict
- hive.txn.manager - org.apache.hadoop.hive.ql.lockmgr.DbTxnManager
Server Side (Metastore)
- hive.compactor.initiator.on - true (자세한 내용은 아래 테이블 참고)
- hive.compactor.cleaner.on - true (자세한 내용은 아래 테이블 참고)
- hive.compactor.worker.threads - Thrift metastore 서비스의 적어도 한 인스턴스에서 양수
다음 섹션은 Hive 트랜잭션과 컴팩션에 영향을 주는 모든 구성 매개변수를 나열해요. 위의 Limitations와 아래의 Table Properties도 참고해요.
트랜잭션을 위한 새 구성 매개변수
트랜잭션을 지원하기 위해 시스템에 여러 새 구성 매개변수가 추가됐어요.
| 구성 키 | 값 | 위치 | 비고 |
|---|---|---|---|
| hive.txn.manager | 기본: org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager트랜잭션에 필요한 값: org.apache.hadoop.hive.ql.lockmgr.DbTxnManager | Client/HiveServer2 | DummyTxnManager는 Hive-0.13 이전 동작을 재현하며 트랜잭션을 제공하지 않음 |
| hive.txn.strict.locking.mode | 기본: true | Client/HiveServer2 | strict 모드에서 non-ACID 리소스는 표준 R/W 락 의미론을 사용, 예: INSERT는 배타적 락 획득. non-strict 모드에서 non-ACID 리소스의 INSERT는 공유 락만 획득, 같은 파티션에 두 동시 쓰기를 허용하지만 테이블이 쓰여지는 동안 lock manager가 DROP TABLE 등을 방지하게 함 (Hive 2.2.0 기준) |
| hive.txn.timeout deprecated. 대신 metastore.txn.timeout 사용 | 기본: 300 | Client/HiveServer2/Metastore | 클라이언트가 하트비트를 보내지 않으면 트랜잭션이 중단 선언되는 시간(초). 이 속성은 모든 구성 요소/서비스에서 같은 값을 가져야 함. 5 |
| hive.txn.heartbeat.threadpool.size deprecated - 여전히 사용 중 | 기본: 5 | Client/HiveServer2 | 하트비트에 사용할 스레드 수 (Hive 1.3.0 및 2.0.0 기준) |
| hive.timedout.txn.reaper.start deprecated | 기본: 100s | Metastore | metastore 시작 후 첫 reaper(타임아웃된 트랜잭션을 중단하는 프로세스) 실행까지의 시간 지연 (Hive 1.3.0 기준). 위의 AcidHouseKeeperService 제어 |
| hive.timedout.txn.reaper.interval deprecated | 기본: 180s | Metastore | reaper(타임아웃된 트랜잭션을 중단하는 프로세스)가 실행되는 간격 (Hive 1.3.0 기준). 위의 AcidHouseKeeperService 제어 |
| hive.txn.max.open.batch deprecated. 대신 metastore.txn.max.open.batch 사용 | 기본: 1000 | Client | open_txns() 한 번의 호출에서 가져올 수 있는 최대 트랜잭션 수. 1 |
| hive.max.open.txns deprecated. 대신 metastore.max.open.txns 사용. | 기본: 100000 | HiveServer2/Metastore | 최대 열린 트랜잭션 수. 현재 열린 트랜잭션이 이 한도에 도달하면 수가 아래로 내려갈 때까지 향후 열기 요청이 거부됨 (Hive 1.3.0 및 2.1.0 기준) |
| hive.count.open.txns.interval deprecated. 대신 metastore.count.open.txns.interval 사용. | 기본: 1s | HiveServer2/Metastore | 열린 트랜잭션 수를 세기 위한 검사 간격(초) (Hive 1.3.0 및 2.1.0 기준) |
| hive.txn.retryable.sqlex.regex deprecated. 대신 metastore.txn.retryable.sqlex.regex 사용. | 기본: "" (빈 문자열) | HiveServer2/Metastore | Hive metastore 데이터베이스에 적합한, 재시도 가능한 SQLException의 SQL state, 오류 코드, 오류 메시지에 대한 정규식 패턴의 콤마 구분 목록 (Hive 1.3.0 및 2.1.0 기준). 예는 Configuration Properties 참고 |
| hive.compaction.merge.enabled | 기본: false | HiveServer2 | ORC delta 파일이 적을 때의 컴팩션 최적화인 merge 기반 컴팩션 활성화 |
| hive.compactor.initiator.duration.update.interval | 기본: 60s | HiveServer2 | compaction_initiator_duration 메트릭의 갱신 간격을 이끄는 시간(초). 값이 작을수록 세밀한 메트릭 갱신. 값이 0 이하이면 이 updater를 끌 수 있고 이 경우 위 메트릭은 initiator가 한 주기를 완료한 후에만 갱신됨. Initiator를 활성화하려면 hive.compactor.initiator.on을 켜야(true) 하며, 그렇지 않으면 이 설정은 효과가 없음 |
| hive.compactor.initiator.on deprecated. 대신 metastore.compactor.initiator.on 사용. | 기본: false트랜잭션에 필요한 값: true (Thrift metastore 서비스의 정확히 한 인스턴스에 대해) | Metastore | 이 metastore 인스턴스에서 initiator 스레드를 실행할지 여부. Hive 1.3.0 이전에는 정확히 하나의 독립형 metastore 서비스 인스턴스에서 활성화하는 것이 중요했음(아직 강제되지 않음). Hive 1.3.0부터 이 속성은 임의 개수의 독립형 metastore 인스턴스에서 활성화할 수 있음 |
| hive.compactor.cleaner.duration.update.interval | 기본: 60s | HiveServer2 | compaction_cleaner_duration 메트릭의 갱신 간격을 이끄는 시간(초). 값이 작을수록 세밀한 메트릭 갱신. 값이 0 이하이면 이 updater를 끌 수 있고 이 경우 위 메트릭은 cleaner가 한 주기를 완료한 후에만 갱신됨 |
| hive.compactor.cleaner.on deprecated. 대신 metastore.compactor.cleaner.on 사용. | 기본: false트랜잭션에 필요한 값: true (Thrift metastore 서비스의 정확히 한 인스턴스에 대해) | Metastore | 이 metastore 인스턴스에서 cleaner 스레드를 실행할지 여부. Hive 4.0.0 이전에는 cleaner 스레드를 hive.compactor.initiator.on으로 시작/중지할 수 있었음. 이 구성은 initiator/cleaner 스레드를 독립적으로 활성화/비활성화하는 데 도움 |
| hive.compactor.cleaner.threads.num | 기본: 1 | HiveServer2 | 컴팩션 후 디렉토리 정리 병렬화 활성화. 많은 파일 관련 검사를 포함하며 비용이 들 수 있음 |
| hive.compactor.compact.insert.only | 기본: true | HiveServer2 | 컴팩터가 insert-only 테이블을 컴팩션할지 여부. 안전 스위치 |
| hive.compactor.crud.query.based | 기본: false | HiveServer2 | 전체 CRUD 테이블의 컴팩션이 쿼리를 통해 수행됨을 의미. insert-only 테이블의 컴팩션은 이 구성 값과 무관하게 항상 쿼리를 통해 실행됨 |
| hive.compactor.gather.stats | 기본: true | HiveServer2 | true로 설정하면 테이블/파티션에 이미 통계가 연결되어 있을 때 MAJOR compaction이 통계를 수집. 리소스를 절약하고 통계를 어차피 사용하지 않으려면 끄기. HIVE_MR_COMPACTOR_GATHER_STATS 구성의 대체이며, MR 및 Query 기반 컴팩션 모두에 동작 |
| metastore.compactor.initiator.failed.retry.time | 기본: 7d | Metastore | Initiator가 metastore.compactor.initiator.failed.compacts.threshold를 무시하고 컴팩션을 다시 시도할 때까지의 시간. 수동 개입 없이 이전 실패 컴팩션이 있는 테이블을 자동 치유하려 시도. 0 또는 음수로 설정하면 이 기능 비활성화 |
| metastore.compactor.long.running.initiator.threshold.warning | 기본: 6h | Metastore | 경고가 기록되는 Initiator 주기 길이. 기본 시간 단위: 시간 |
| metastore.compactor.long.running.initiator.threshold.error | 기본: 12h | Metastore | 오류가 기록되는 Initiator 주기 길이. 기본 시간 단위: 시간 |
| hive.compactor.worker.sleep.time | *기본:*10800ms | HiveServer2 | 실행된 잡이 없거나 오류가 있는 경우 worker 스레드가 다른 반복을 시작하기 전에 잠드는 시간(밀리초) |
| hive.compactor.worker.max.sleep.time | 기본: 320000ms | HiveServer2 | 실행된 잡이 없거나 오류가 있는 경우 worker 스레드가 다른 반복을 시작하기 전의 최대 잠드는 시간(밀리초). 백오프에 사용 |
| hive.compactor.worker.threads deprecated. 대신 metastore.compactor.worker.threads 사용. | 기본: 0트랜잭션에 필요한 값: Thrift metastore 서비스의 적어도 한 인스턴스에서 > 0 | Metastore | 이 metastore 인스턴스에서 실행할 컴팩터 worker 스레드 수. 2 |
| hive.compactor.worker.timeout | 기본: 86400s | Metastore | 컴팩션 잡이 실패로 선언되고 컴팩션이 다시 큐에 들어가는 시간(초) |
| hive.compactor.cleaner.run.interval | 기본: 5000ms | Metastore | cleaner 스레드 실행 사이의 시간(밀리초) (Hive 0.14.0 이후) |
| hive.compactor.check.interval | 기본: 300s | Metastore | 컴팩션해야 할 테이블/파티션이 있는지 검사 사이의 시간(초). 3 |
| hive.compactor.delta.num.threshold | 기본: 10 | Metastore | minor 컴팩션을 트리거하는 테이블/파티션의 delta 디렉토리 수 |
| hive.compactor.delta.pct.threshold | 기본: 0.1 | Metastore | major 컴팩션을 트리거하는 base에 대한 delta 파일의 백분율(분수) 크기. 1 = 100%, 따라서 기본 0.1 = 10% |
| hive.compactor.abortedtxn.threshold | 기본: 1000 | Metastore | major 컴팩션을 트리거하는 주어진 테이블/파티션과 관련된 중단된 트랜잭션 수 |
| hive.compactor.aborted.txn.time.threshold | 기본: 12h | Metastore | 컴팩션이 트리거될 때의 테이블/파티션의 가장 오래된 중단 트랜잭션의 수명. 기본 시간 단위: 시간. 비활성화하려면 음수로 설정 |
| hive.compactor.max.num.delta | 기본: 500 | Metastore | 컴팩터가 단일 잡에서 처리하려 시도할 최대 delta 파일 수 (Hive 1.3.0 기준). 4 |
| hive.compactor.job.queue | 기본: "" (빈 문자열) | Metastore | 컴팩션 잡이 제출될 Hadoop 큐 이름 지정에 사용. 큐를 Hadoop이 선택하게 하려면 빈 문자열로 설정 (Hive 1.3.0 기준) |
| hive.compactor.request.queue | 기본: 1 | HiveServer2 | 많은 파일 메타데이터 검사를 포함하고 비용이 들 수 있는 checkForCompaction 연산의 병렬화 활성화 |
| hive.split.grouping.mode | 기본: query (허용 값: query, compactor) | HiveServer2 | 쿼리 기반 컴팩터 안에서 compactor로 설정됨. 이것은 Tez SplitGrouper가 버킷 번호를 기반으로 스플릿을 그룹화해, 서로 다른 버킷 파일의 같은 버킷 번호의 모든 행이 컴팩션 후 같은 버킷 파일에 끝나도록 함 |
| hive.txn.xlock.iow | 기본: true | HiveServer2 | INSERT OVERWRITE 같은 OVERWRITE가 있는 명령이 transactional 테이블에 대해 배타적 락을 획득하도록 보장. 이는 동시에 실행되는 insert(overwrite 없는)가 INSERT OVERWRITE에 숨겨지지 않도록 보장 |
| hive.txn.xlock.write | 기본: true | HiveServer2 | ACID 리소스에 대한 동시성 수준 관리. 커밋 단계에서 공유 쓰기와 쓰기-쓰기 충돌 해결을 활성화해 더 나은 쿼리 병렬성 제공. - true이면 배타적 쓰기 사용: - INSERT OVERWRITE는 EXCLUSIVE 락 획득 - UPDATE/DELETE는 EXCL_WRITE 락 획득 - INSERT는 SHARED_READ 락 획득 - false이면 공유 쓰기, 충돌 변경이 있으면 트랜잭션이 중단: - INSERT OVERWRITE는 EXCL_WRITE 락 획득 - INSERT/UPDATE/DELETE는 SHARED_READ 락 획득 |
| metastore.acidmetrics.ext.on | 기본: true | HiveServer2 | acid metrics 서비스 외부에서 추가 acid 관련 메트릭을 수집할지 여부 (metastore.metrics.enabled 및/또는 hive.server2.metrics.enabled도 true로 설정해야 함) |
| Compaction History | |||
| hive.compactor.history.retention.succeeded deprecated. 대신 metastore.compactor.history.retention.succeeded 사용 | 기본: 3 | Metastore | 이력에 보존할 성공 컴팩션 항목 수 (파티션당) |
| hive.compactor.history.retention.failed deprecated. 대신 metastore.compactor.history.retention.failed 사용. | 기본: 3 | Metastore | 이력에 보존할 실패 컴팩션 항목 수 (파티션당) |
| hive.compactor.history.retention.attempted deprecated. 대신 metastore.compactor.history.retention.did.not.initiate 사용. | 기본: 2 | Metastore | 이력에 보존할 시도 컴팩션 항목 수 (파티션당) |
| hive.compactor.initiator.failed.compacts.threshold deprecated. 대신 metastore.compactor.initiator.failed.compacts.threshold 사용. | 기본: 2 | Metastore | 주어진 파티션에 대한 연속 실패 컴팩션 수. 이를 초과하면 Initiator가 컴팩션 자동 스케줄링 시도를 중지. ALTER TABLE로 컴팩션을 시작하는 것은 여전히 가능. 수동 시작 컴팩션이 성공하면 자동 시작 컴팩션이 재개됨. 이 값은 hive.compactor.history.retention.failed보다 작아야 함. |
| metastore.compactor.initiator.failed.compacts.threshold | 기본: 2 (1과 20 사이 허용) | Metastore | 연속 컴팩션 실패 수(테이블/파티션당)를 초과하면 더 이상 자동 컴팩션이 스케줄링되지 않음. 이 값은 hive.compactor.history.retention.failed보다 작아야 함. |
| hive.compactor.history.reaper.interval deprecated. metastore.acid.housekeeper.interval이 처리함. | 기본: 2m | Metastore | 컴팩션의 역사적 기록을 제거하는 프로세스가 실행되는 빈도를 제어 |
| ACID metrics | |||
| metastore.acidmetrics.check.interval | 기본: 300s | Metastore | acid 관련 메트릭 수집 실행 사이의 시간(초) |
| metastore.acidmetrics.thread.on | 기본: true | Metastore | 이 metastore 인스턴스에서 acid 관련 메트릭 수집을 실행할지 여부 |
| metastore.deltametrics.delta.num.threshold | 기본: 100 | Metastore | 테이블/파티션이 ACID 메트릭 보고서에 포함되기 위해 가져야 하는 활성 delta 파일의 최소 수 |
| metastore.deltametrics.delta.pct.threshold | 기본: 0.01 | Metastore | base 디렉토리에 대한 delta 파일의 백분율(분수) 크기. 이 임계값보다 작은 delta는 작은 delta로 계산. 기본 0.01 = 1% |
| metastore.deltametrics.max.cache.size | 기본: 100 (0과 500 사이 허용) | Metastore | ACID 메트릭 캐시 크기, 즉 활성/오래된/작은 delta 목록에 포함될 delta가 가장 많은 파티션과 비파티션 테이블의 최대 수. 허용 범위 0~500 |
| metastore.deltametrics.obsolete.delta.num.threshold | 기본: 100 | Metastore | 테이블/파티션이 ACID 메트릭 보고서에 포함되기 위해 가져야 하는 오래된(obsolete) delta 파일의 최소 수 |
- metastore.txn.max.open.batch는 Flume이나 Storm 같은 스트리밍 에이전트가 동시에 여는 트랜잭션 수를 제어해요. 스트리밍 에이전트는 그 수의 항목을 단일 파일(Flume 에이전트나 Storm bolt당)에 써요. 따라서 이 값을 늘리면 스트리밍 에이전트가 만드는 delta 파일 수가 줄어들어요. 하지만 동시에 Hive가 추적해야 하는 열린 트랜잭션 수도 늘어나 읽기 성능에 부정적 영향을 줄 수 있어요.
- Worker 스레드는 컴팩션을 하는 MapReduce 잡을 생성해요. 컴팩션 자체를 하는 건 아니에요. worker 스레드 수를 늘리면 컴팩션 필요하다고 판단된 테이블/파티션이 컴팩션되는 시간이 줄어요. 또한 더 많은 MapReduce 잡이 백그라운드에서 실행되므로 Hadoop 클러스터의 백그라운드 부하도 늘어나요. 각 컴팩션은 한 번에 한 파티션(또는 비파티션이면 전체 테이블)을 처리할 수 있어요.
- 이 값을 줄이면 컴팩션이 필요한 테이블/파티션에 대해 컴팩션이 시작되기까지의 시간이 줄어요. 하지만 컴팩션 필요 여부를 확인하려면 마지막 major 컴팩션 이후 트랜잭션이 수행된 각 테이블/파티션에 대해 NameNode에 여러 번 호출해야 해요. 따라서 이 값을 줄이면 NameNode 부하가 늘어나요.
- 컴팩터가 매우 많은 수의 delta 파일을 감지하면 먼저 여러 부분 minor 컴팩션(현재 순차)을 실행한 다음 실제로 요청된 컴팩션을 수행해요.
- 값이 같지 않으면 활성 트랜잭션이 "timed out"으로 판단되고 그에 따라 중단(Aborted)될 수 있어요. 이는 "No such transaction...", "No such lock ..." 같은 오류를 초래해요.
INSERT, UPDATE, DELETE에 설정할 구성 값
위의 새 매개변수 외에도, 기존 매개변수 몇 개를 INSERT ... VALUES, UPDATE, DELETE 지원을 위해 설정해야 해요.
| 구성 키 | 설정해야 하는 값 |
|---|---|
| hive.support.concurrency | true (기본은 false) |
| hive.enforce.bucketing | true (기본은 false) (Hive 2.0부터 필수 아님) |
| hive.exec.dynamic.partition.mode | nonstrict (기본은 strict) |
컴팩션에 설정할 구성 값
시스템의 데이터가 Hive 사용자(Hive metastore가 실행되는 사용자)가 소유하지 않은 경우, 컴팩션을 수행하려면 Hive가 데이터를 소유한 사용자로 실행할 권한이 필요해요. HiveServer2를 이미 사용자를 가장(impersonate)하도록 설정했다면 남은 작업은 Hive가 metastore를 실행하는 호스트에서 사용자를 가장할 권리가 있음을 보장하는 것뿐이에요. 이는 Hadoop의 core-site.xml 파일에 hadoop.proxyuser.hive.hosts에 호스트 이름을 추가해 이루어져요. 아직 하지 않았다면 Hive를 프록시 사용자로 작동하도록 구성해야 해요. 이는 Hive metastore를 실행하는 사용자용 keytab을 설정하고 Hadoop의 core-site.xml 파일에 hadoop.proxyuser.hive.hosts와 hadoop.proxyuser.hive.groups를 추가해야 해요. Hadoop 버전의 보안 모드에 대한 Hadoop 문서를 참고해요(예: Hadoop 2.5.1의 경우 Hadoop in Secure Mode).
컴팩션 풀링 (Compaction pooling)
컴팩션 풀링에 대한 자세한 내용은 여기에서 볼 수 있어요: Compaction pooling
테이블 속성 (Table Properties)
테이블이 ACID 쓰기(insert, update, delete)에 사용되려면 Hive 0.14.0부터 그 테이블에 "transactional=true" 테이블 속성을 설정해야 해요. 일단 TBLPROPERTIES("transactional"="true")로 테이블을 ACID 테이블로 정의하면 non-ACID 테이블로 되돌릴 수 없어요, 즉 TBLPROPERTIES("transactional"="false")로 변경하는 것은 허용되지 않아요. 또한 hive.txn.manager는 hive-site.xml에 또는 어떤 쿼리를 실행하기 전에 세션 시작 부분에서 org.apache.hadoop.hive.ql.lockmgr.DbTxnManager로 설정되어야 해요. 이 설정이 없으면 insert는 예전 스타일로 수행되고, HIVE-11716 이전에는 update와 delete가 금지돼요. HIVE-11716 이후로는 DbTxnManager 없이 ACID 테이블에 대한 연산이 허용되지 않아요. 그러나 Hive 0.13.0에는 적용되지 않아요.
테이블 소유자가 언제 컴팩션할지 시스템이 자동 결정하기를 원하지 않으면 "NO_AUTO_COMPACTION" 테이블 속성을 설정할 수 있어요. 이는 모든 자동 컴팩션을 막아요. 수동 컴팩션은 Alter Table/Partition Compact 문으로 여전히 할 수 있어요.
테이블 속성은 Hive Data Definition Language의 Create Table 및 Alter Table Properties 섹션에서 설명하듯이 테이블 생성 또는 변경 시 TBLPROPERTIES 절로 설정돼요. "transactional" 및 "NO_AUTO_COMPACTION" 테이블 속성은 Hive 릴리스 0.x와 1.0에서 대소문자를 구분하지만, 릴리스 1.1.0부터는 대소문자를 구분하지 않아요 (HIVE-8308).
더 많은 컴팩션 관련 옵션은 Hive 1.3.0 및 2.1.0부터 TBLPROPERTIES로 설정할 수 있어요. CREATE TABLE로 테이블 수준에서, ALTER TABLE/PARTITION COMPACT로 요청 수준에서 설정할 수 있어요. 이들은 웨어하우스/테이블 전체 설정을 재정의하는 데 사용돼요. 예를 들어 MR 속성을 재정의해 컴팩션 잡에 영향을 주려면 CREATE TABLE 문이나 ALTER TABLE로 컴팩션을 명시적으로 시작할 때 "compactor.
예: TBLPROPERTIES에서 테이블 수준 컴팩션 옵션 설정
CREATE TABLE table_name (
id int,
name string
)
CLUSTERED BY (id) INTO 2 BUCKETS STORED AS ORC
TBLPROPERTIES ("transactional"="true",
"compactor.mapreduce.map.memory.mb"="2048", -- 컴팩션 map job 속성 지정
"compactorthreshold.hive.compactor.delta.num.threshold"="4", -- delta 디렉토리가 4개보다 많으면 minor 컴팩션 트리거
"compactorthreshold.hive.compactor.delta.pct.threshold"="0.5" -- delta 파일 크기 대비 base 파일 크기 비율이
-- 50%보다 크면 major 컴팩션 트리거
);
예: TBLPROPERTIES에서 요청 수준 컴팩션 옵션 설정
ALTER TABLE table_name COMPACT 'minor'
WITH OVERWRITE TBLPROPERTIES ("compactor.mapreduce.map.memory.mb"="3072"); -- 컴팩션 map job 속성 지정
ALTER TABLE table_name COMPACT 'major'
WITH OVERWRITE TBLPROPERTIES ("tblprops.orc.compress.size"="8192"); -- 다른 Hive 테이블 속성 변경
강연 및 발표 (Talks and Presentations)
Cloudera 미트업의 Kokila N이 The Art of Compaction presented (영문).
Dataworks Summit 2017, San Jose, CA, USA에서 Eugene Koifman의 Transactional Operations In Hive
DataWorks Summit 2018, San Jose, CA, USA - Hive 3와 ACID V2 기능 포함
더 알아보기 (Learn more)
- Streaming Data Ingest에서 스트리밍 쓰기 API를 확인할 수 있어요.
- Compaction pooling에서 컴팩션 풀링에 대해 더 볼 수 있어요.