이번 글에서는 저번 글에 이어, Trino의 Trino web UI에 대한 설명과 다른 쿼리 엔진들과의 성능을 간단하게 비교해 볼 예정입니다. 해당 글에서는 Trino web UI와 Trino의 성능 비교 및 간단 튜닝을 목표로 합니다.
QUERY DETAILS
Trino web UI → Query details (실행된 쿼리들을 확인 가능합니다.)
- Completed splits : 쿼리에 대한 Completed splits의 수를 나타냅니다. 쿼리 실행 시, 0으로 시작하며 쿼리 실행 중에 Split가 완료되면 증가합니다.
- Running splits : 쿼리에 대한 Running 중인 splits의 수를 나타내며, 모두 완료가 되면 0이 됩니다.
- Queued splits : Queued 상태와 running 상태에서 split 수가 변하며, 쿼리가 완료되면 0이 됩니다.
- Wall time : 쿼리를 실행하는데 소요되는 총 시간입니다. (queue 대기열에 에 있는 시간 제외)
- Total wall time : 쿼리를 실행하는데 소요되는 총 시간입니다. (queue 대기열에 에 있는 시간 포함)
- CPU time : 쿼리를 처리하는데 소요되는 총 CPU 시간이며, worker의 스레드 간의 병렬 실행이 모두 별도로 계산되어 합산되기 때문에 wall time 보다 크게 기록되곤 합니다. 예를 들어, 4개의 CPU가 쿼리를 처리하는데 1초를 소비했다면 총 CPU 시간은 4초입니다.
- Current total Reserved Memory : 쿼리 실행 동안, 현재 reserved된 총 메모리 양입니다. 쿼리가 완료되면 0이 됩니다.
- Peak Total memory : 쿼리 실행 중, 최대 총 메모리 사용량입니다. 특정 Operation에 많은 메모리가 필요할 수 있습니다.
- Cumulative user memory : 쿼리 처리 전반에 걸친, 누적 사용자 메모리입니다. 메모리의 누적량입니다. (동시에 해당 메모리가 사용되었다는 뜻 은 아닙니다.)
QUERY DETAILS (실제 쿼리 Details)
# 테스트 쿼리
select count(*) from {catalog}.{DB}.{Table}
쿼리를 실행함으로써의 Stage, taks 등의 과정을 확인할 수 있습니다. Stage는 쿼리를 분산 실행하는 단위이며, Stage1에서 각 worker들이 할당된 task를 분산해서 조회합니다. Stage-0과 Stage-1에서 조회된 결과를 Coordinator에게 집계하여 전달하는 단계로 총 두 단계의 Stages로 구성된 것으로 확인됩니다.
QUERY 성능 비교
Trino, Hive (MapReduce, Tez, Spark) 속도 비교
- 비교 대상 쿼리 / 테이블 정보
hive.test_db.table_1 (count(*)) | hive.test_db.table_2 (count(*)) | |
Size | 185.9G | 12.0877G |
Count | 1300796948 (약 13억) | 89609753 (약 8천9백만) |
- select count(*) 쿼리문 수행 시 시간 비교
Execution in Seconds | ||||
Trino | Hive - MapReduce | Hive - Tez | Hive - Spark | |
table_1 (Query 1) | 109 | 1663.425 | 204.642 | 163.474 |
table_2 (Query 2) | 6.36 | 56.114 | 11.432 | 52.212 |
성능은 데이터 크기, 데이터 속성, 파티션유무, 버켓팅 유무, 사용자 쿼리의 종류에 따라 달라질 수 있다. 성능만을 비교했을 때, Trino - Hive (tez), Hive (spark), Hive (MR) 순으로 확인되며, Trino의 실행 속도가 가장 빠른 것으로 확인됩니다.
추가 튜닝 포인트
trino:sf100> SELECT
-> (SELECT name FROM table_1 r WHERE regionkey = n.regionkey) AS region_name,
-> n.name AS nation_name,
-> sum(totalprice) orders_sum
-> FROM table_1 n, table_2 o, table_3 c
-> WHERE n.nationkey = c.nationkey
-> AND c.custkey = o.custkey
-> GROUP BY n.nationkey, regionkey, n.name
-> ORDER BY orders_sum DESC
-> ;
Query 20221019_110021_00011_3r73g, FAILED, 2 nodes
Splits: 59 total, 28 done (47.46%)
58.55 [60.2M rows, 0B] [1.03M rows/s, 0B/s]
Query 20221019_110021_00011_3r73g failed: Query exceeded per-node memory limit of 1GB [Allocated: 1010.05MB,
Delta: 98.32MB, Top Consumers: {HashBuilderOperator=1003.09MB, ExchangeOperator=4.45MB,
PartitionedOutputOperator=2.51MB}]
Trino를 통해 쿼리를 수행하다보면, 위와 같이 "failed: Query exceeded per-node memory limit of 1GB" error가 발생하는 경우가 있습니다. 해당 원인은 worker노드에서 처리할 수 있는 데이터의 memory가 limit를 초과해 발생하게 됩니다.
Trino web UI에서 Query detail을 확인해보면, peak memory가 1.81GB (2개의 worker)에서 쿼리가 중단된 것을 확인할 수 있습니다. 이런 경우, config.properties → query.max-memory-per-node의 기존 1G 설정을 더 높게 수정 해야합니다.
coordinator=False
http-server.http.port=9999
query.max-memory=8G # 2개 worker-node의 query.max-memory-per-node 합
query.max-memory-per-node=4G # 기존 1G에서 4G로 수정
이후, 다시 동일 쿼리를 수행하면, 정상적으로 쿼리가 수행되는 것으로 확인됩니다.
Peak memory를 보면 7.56G를 사용했는데, 각 Worker노드의 query.max-memory-per-node를 4G로 설정하였기 때문에 쿼리에 대한 메모리 사용량이 늘어난 것이 확인됩니다.
'Bigdata Components > Trino' 카테고리의 다른 글
[Trino] Trino의 구조 및 설정 (0) | 2024.01.07 |
---|---|
[Trino] Trino 기본 개념 및 이해하기 (0) | 2024.01.07 |