지구정복
[Trino] Query exceeded per-node memory limit of 1GB | Trino Memory Tunning 본문
[Trino] Query exceeded per-node memory limit of 1GB | Trino Memory Tunning
noohhee 2025. 2. 18. 14:42
Hue에서 트리노 사용중 아래 에러가 발생.
{'message': 'Query exceeded per-node memory limit of 1GB [Allocated: 1015.31MB, Delta: 11.74MB, Top Consumers: {TableScanOperator=588.89MB, OrderByOperator=379.89MB, LazyOutputBuffer=46.53MB}]', 'errorCode': 131079, 'errorName': 'EXCEEDED_LOCAL_MEMORY_LIMIT', 'errorType': 'INSUFFICIENT_RESOURCES', 'failureInfo': {'type': 'io.trino.ExceededMemoryLimitException', 'message': 'Query exceeded per-node memory limit of 1GB [Allocated: 1015.31MB, Delta: 11.74MB, Top Consumers: {TableScanOperator=588.89MB, OrderByOperator=379.89MB, LazyOutputBuffer=46.53MB}]', 'suppressed': [], 'stack': io.trino.ExceededMemoryLimitException.exceededLocalUserMemoryLimit(ExceededMemoryLimitException.java:40) io.trino.memory.QueryContext.enforceUserMemoryLimit(QueryContext.java:320) io.trino.memory.QueryContext.updateUserMemory(QueryContext.java:161) io.trino.memory.QueryContext.lambda$addTaskContext$0(QueryContext.java:241) io.trino.memory.QueryContext$QueryMemoryReservationHandler.reserveMemory(QueryContext.java:301) io.trino.memory.context.RootAggregatedMemoryContext.updateBytes(RootAggregatedMemoryContext.java:37) io.trino.memory.context.ChildAggregatedMemoryContext.updateBytes(ChildAggregatedMemoryContext.java:38) io.trino.memory.context.SimpleLocalMemoryContext.setBytes(SimpleLocalMemoryContext.java:66) io.trino.operator.DirectExchangeClient.updateRetainedMemory(DirectExchangeClient.java:328) io.trino.operator.DirectExchangeClient.addPages(DirectExchangeClient.java:307) io.trino.operator.DirectExchangeClient$ExchangeClientCallback.addPages(DirectExchangeClient.java:387) io.trino.operator.HttpPageBufferClient$1.onSuccess(HttpPageBufferClient.java:416) io.trino.operator.HttpPageBufferClient$1.onSuccess(HttpPageBufferClient.java:347) cohttp://m.google.common.util.concurrent.Futures$CallbackListener.run(Futures.java:1138) java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) java.base/java.lang.Thread.run(Thread.java:833) |
trino-config-properties에서 아래 설정값들을 조정해줘야 한다.
설정값 설명은 다음과 같다.
(참고 https://trino.io/docs/current/admin/properties-resource-management.html)
* query.max-cpu-time
Default value: 1_000_000_000d
This is the max amount of CPU time that a query can use across the entire cluster. Queries that exceed this limit are killed.
* query.max-memory-per-node
Default value: (JVM max memory * 0.3)
This is the max amount of user memory a query can use on a worker.
User memory is allocated during execution for things that are directly attributable to, or controllable by, a user query.
For example, memory used by the hash tables built during execution, memory used during sorting, etc.
When the user memory allocation of a query on any worker hits this limit, it is killed.
Warning
The sum of query.max-memory-per-node and memory.heap-headroom-per-node must be less than the maximum heap size in the JVM on the node.
See JVM config.
* query.max-memory
Default value: 20GB
This is the max amount of user memory a query can use across the entire cluster.
When the user memory allocation of a query across all workers hits this limit it is killed.
Warning
query.max-total-memory must be greater than query.max-memory.
* query.max-total-memory
Default value: (query.max-memory * 2)
This is the max amount of memory a query can use across the entire cluster, including revocable memory.
When the memory allocated by a query across all workers hits this limit it is killed.
The value of query.max-total-memory must be greater than query.max-memory.
* memory.heap-headroom-per-node
Default value: (JVM max memory * 0.3)
This is the amount of memory set aside as headroom/buffer in the JVM heap for allocations that are not tracked by Trino.
Warning
The sum of query.max-memory-per-node and memory.heap-headroom-per-node must be less than the maximum heap size in the JVM on the node.
See JVM config.
위 설정값들의 최적값은 어떻게 될까?
아래 잘 정리된 글을 보고 먼저 트리노 메모리 구조 이해가 필요하다.
https://it-sunny-333.tistory.com/102
[Presto] Memory Pool / Memory configuration (config.properties)
Presto Memory 각 Memory Pool 에서 메모리를 할당한다. 무조건 General Pool에서 먼저 할당한다. 메모리의 종류는 2가지이다. user 메모리 group by, join 등 쿼리에 따른 메모리이다. system 메모리 input/output buffer
it-sunny-333.tistory.com
트리노 각 노드 메모리( JVM Memory ) = General Memory Pool + Reserved Memory Pool + Headroom Memory
General Memory는 일반적인 쿼리를 실행하는 메모리 pool이라 이해하면 된다.
Reserved Memory는 General Pool 할당 메모리를 초과하는 무거운 쿼리를 실행 할 때, 해당 쿼리를 Reserved Pool로 보내져 실행된다.
단 1개의 쿼리만 보낼 수 있고, 메모리 사용량이 제일 많은 쿼리부터 실행한다.
만약 JVM xmx값이 150GB이고, default값으로 확인해보면 다음과 같다.
JVM Memory(150GB)
= General Memory Pool + Reserved Memory Pool(JVM Max Memory * 0.3) + Headroom Memory (JVM Max Memory * 0.3)
= General + Reserved(query.max-total-memory-per-node) + Headroom(memory.heap-headroom-per-node)
= General Memory Pool + 45GB + 45GB
( General Memory Pool는 60GB로 유추가능 )
만약 Reserved Pool을 사용하고 싶지 않다면, (General Pool 만 사용함) 아래 설정을 해준다.
experimental.reserved-pool-enabled = false
General Pool 만 사용하면 쿼리 동시성은 더 높아진다. Reserved Pool 에서는 1개의 쿼리만 실행 가능하므로.
따라서 일단은 기본값으로 셋팅해보고 사용해본다.
JVM -Xmx 150G인 경우
query.max-memory = (150 - headroom memory) / 2 = 105 / 2 = 50
query.max-total-memory(default) = query.max-memory * 2 = 100
query.max-memory-per-node(default) = 설정값에서 제거하여 default값 사용하게 하든지 명시적으로 default값 사용하기
= 150 * 0.3 = 45
memory.heap-headroom-per-node(default) = 150 * 0.3 = 45
그럼 정리하면 다음과 같다.
JVM Xmx Memory(150GB) = General(60) + Reserved(45) + Headroom(45)
추가적으로 Trino WEB UI에서 쿼리에 대한 메모리 분석을 할 수 있다.
만약 이렇게 설정했는데도 문제가 생기면 headrooom을 줄이고 Reserved(query.max-memory-per-node) 를 늘려준다.
그럼에도 문제가 되면 experimental.reserved-pool-enabled=false 를 설정하여 reserved memory를 없애고, general memory만 사용하게 한다.
(이러면 동시성 작업의 효율은 증가하지만 큰 쿼리가 있을 경우 다른 쿼리들이 계속 대기할 가능성 있음)
그럼에도 문제가 생기면 아래 설정값을 설정하여 메모리 찼을 때 디스크도 사용하게 한다.
experimental.spill-enabled=true
experimental.max-spill-per-node=80GB
experimental.query-max-spill-per-node=80GB
'데이터 엔지니어링 정복 > Trino' 카테고리의 다른 글
[Trino] SSL/TLS(https) 적용 혹은 만료시 재생성후 배포 | Max retries exceeded with url (0) | 2025.02.13 |
---|