본문으로 건너뛰기
최종 수정: 에

메모리 문제 FAQ

Doris BE 프로세스의 메모리를 분석할 때는 주로 be/log/be.INFO 로그, BE 프로세스 메모리 모니터링(Metrics), Doris Bvar 통계를 사용합니다. OOM Killer가 실행되었다면 dmesg -T 실행 결과를 수집해야 합니다. 쿼리나 데이터 적재 작업의 메모리를 분석하려면 Query Profile을 수집해야 합니다. 이 정보를 바탕으로 일반적인 메모리 문제를 분석할 수 있습니다. 직접 해결하기 어렵다면 Doris 개발자에게 도움을 요청해야 합니다. 어떤 방식(Github에 이슈 등록, Doris 포럼에 이슈 작성, 이메일 또는 WeChat)을 사용하든 문제 설명에 위 정보를 첨부해 주세요.

먼저 현재 관찰된 현상이 어떤 메모리 문제에 해당하는지 파악한 뒤, 추가로 조사합니다. 일반적으로 프로세스 메모리 로그를 먼저 분석해야 합니다. 메모리 로그 분석을 참고하세요. 일반적인 메모리 문제는 다음과 같습니다.

1 쿼리 및 데이터 적재 메모리 제한 오류​

쿼리 및 데이터 적재 오류 메시지에 MEM_LIMIT_EXCEEDED가 표시되면, 프로세스의 가용 메모리가 부족하거나 작업이 단일 실행 메모리 제한을 초과하여 취소되었다는 뜻입니다.

ERROR 1105 (HY000): errCode = 2, detailMessage = (10.16.10.8)[MEM_LIMIT_EXCEEDED] xxxx .

오류 메시지에 Process memory not enough가 포함되어 있으면 프로세스의 가용 메모리가 부족하다는 뜻입니다. 자세한 분석 방법은 쿼리 또는 데이터 적재 오류: 프로세스의 가용 메모리 부족을 참고하세요.

오류 메시지에 memory tracker limit exceeded가 표시되면 작업이 단일 실행 메모리 제한을 초과했다는 뜻입니다. 자세한 분석 방법은 쿼리 또는 데이터 적재 오류: 단일 실행 메모리 제한 초과를 참고하세요.

2 Doris BE OOM 크래시​

BE 프로세스가 비정상 종료된 후 log/be.out에 오류 메시지가 없으면 dmesg -T를 실행하세요. Out of memory: Killed process {pid} (doris_be)가 표시되면 OOM Killer가 실행되었다는 뜻입니다. 자세한 분석 방법은 OOM Killer 크래시 분석을 참고하세요.

3 메모리 누수​

메모리 누수가 의심된다면 최신 세 자리 버전으로 업그레이드하는 것이 가장 좋은 해결 방법입니다. Doris 2.0을 사용 중이라면 Doris 2.0.x의 최신 버전으로 업그레이드하세요. 다른 사용자도 같은 현상을 겪었을 가능성이 높으며, 대부분의 메모리 누수는 버전 업데이트 과정에서 수정되기 때문입니다.

다음 현상이 관찰되면 메모리 누수가 있을 수 있습니다.

  • Doris Grafana 또는 서버 모니터링에서 Doris BE 프로세스의 메모리가 선형으로 계속 증가하며, 클러스터의 작업이 중지된 후에도 메모리가 줄어들지 않는 것으로 나타납니다.

  • Memory Tracker에 통계 누락이 있습니다. 분석 방법은 Memory Tracker를 참고하세요.

메모리 누수는 일반적으로 Memory Tracker의 통계 누락을 동반하므로, 분석 방법은 [Memory Tracker] 섹션도 참고하세요.

4 Doris BE 프로세스의 메모리가 줄어들지 않거나 계속 증가함​

Doris Grafana 또는 서버 모니터링에서 Doris BE 프로세스의 메모리가 선형으로 계속 증가하고, 클러스터의 작업이 중지된 후에도 메모리가 줄어들지 않는 것으로 나타나면, 먼저 Memory Tracker 문서의 Memory Tracker 설명을 참고하여 Memory Tracker에 통계 누락이 있는지 분석합니다. Memory Tracker에 통계 누락이 있다면 원인을 추가로 분석합니다.

Memory Tracker에 통계 누락이 없고 대부분의 메모리가 집계되어 있다면, 개요를 참고하여 Doris BE 프로세스의 각 부분이 메모리를 과도하게 점유하는 이유와 메모리 사용량을 줄이는 방법을 분석합니다.

5 과도한 가상 메모리 사용량​

Label=process virtual memory Memory Tracker는 실시간 가상 메모리 크기를 표시하며, 이 값은 top -p {pid}로 확인한 Doris BE 프로세스의 가상 메모리 크기와 같습니다.

MemTrackerLimiter Label=process virtual memory, Type=overview, Limit=-1.00 B(-1 B), Used=44.25 GB(47512956928 B), Peak=44.25 GB(47512956928 B)

현재 Doris에는 여전히 Doris BE 프로세스의 가상 메모리가 과도하게 커지는 문제가 있습니다. 일반적으로 Jemalloc이 많은 가상 메모리 매핑을 유지하기 때문에 발생하며, 이로 인해 Jemalloc Metadata도 메모리를 과도하게 점유하게 됩니다. Jemalloc Metadata 메모리 분석 방법은 Jemalloc 메모리 분석을 참고하세요.

또한 Doris의 Join Operator와 Column은 메모리를 충분히 재사용하지 않는 것으로 알려져 있습니다. 이 때문에 일부 상황에서 더 많은 가상 메모리를 요청하고, 결국 Jemalloc Retained에 캐시하게 됩니다. 현재로서는 적절한 해결 방법이 없습니다. Doris BE 프로세스를 주기적으로 재시작하는 것을 권장합니다.

6 BE 프로세스를 시작한 직후 프로세스 메모리가 매우 큼​

일반적으로 BE 프로세스 시작 시 로드하는 메타데이터의 메모리 사용량이 너무 크기 때문입니다. 메타데이터 메모리 분석을 참고하여 Doris BE Bvar를 확인하세요.

  • doris_total_tablet_num이 너무 크면 일반적으로 테이블의 파티션 수와 버킷 수가 너무 많기 때문입니다. {fe_host}:{fe_http_port}/System?path=//dbs를 확인하여 tablet이 많은 테이블을 찾으세요. 테이블의 tablet 수는 파티션 수에 버킷 수를 곱한 값과 같습니다. 파티션 수와 버킷 수를 줄여 보세요. 또는 더 이상 사용하지 않을 오래된 테이블이나 파티션을 삭제하세요.

  • doris_total_rowset_num이 너무 크지만 tablet 수는 적다면, SHOW-PROC 문서를 참고하여 rowset은 많고 tablet은 적은 테이블을 찾은 다음, 수동으로 compaction을 실행하거나 자동 compaction이 완료될 때까지 기다리세요. 자세한 내용은 메타데이터 관리 관련 문서를 참고하세요. rowset이 수십만 개라면 메타데이터가 몇 GB를 점유하는 것은 정상입니다.

  • tablet_meta_schema_columns_count가 너무 커서 doris_total_tablet_schema_num보다 수백 배 또는 수천 배 크다면, 클러스터에 수백 개 또는 수천 개의 컬럼을 가진 대규모 와이드 테이블이 있다는 뜻입니다. 이 경우 tablet 수가 같아도 더 많은 메모리를 점유합니다.

7 복잡한 연산자 없이 데이터를 스캔하기만 하는 쿼리가 메모리를 많이 사용함​

Segment를 읽을 때 여는 Column Reader와 Index Read가 메모리를 점유하기 때문일 수 있습니다. 메타데이터 메모리 분석을 참고하여 Doris BE Bvar에서 doris_total_segment_num, doris_column_reader_num, doris_ordinal_index_memory_bytes, doris_zone_map_memory_bytes, doris_short_key_index_memory_bytes의 변화를 확인하세요. 이 현상은 대규모 와이드 테이블을 읽을 때도 흔히 발생합니다. 수십만 개의 Column Reader가 열리면 메모리 점유량이 수십 GB에 이를 수 있습니다.

Heap Profile에서 메모리 비중이 큰 호출 스택에 Segment와 ColumnReader 필드가 보이면, Segment를 읽는 과정에서 많은 메모리를 점유하는 것으로 거의 확정할 수 있습니다.

이 경우 SQL을 수정하여 스캔하는 데이터 양을 줄이거나, 테이블 생성 시 지정하는 버킷 크기를 줄여 열리는 Segment 수를 줄이는 방법만 사용할 수 있습니다.

8. 쿼리 취소 중 멈춤​

Doris 2.1.3 이전 버전에서 흔히 발생

쿼리 실행 중 요청한 메모리는 대부분 쿼리가 끝날 때 해제해야 합니다. 프로세스 메모리가 충분하면 일반적으로 쿼리가 얼마나 빨리 또는 느리게 종료되는지 신경 쓸 필요가 없습니다. 하지만 프로세스 메모리가 부족하면 일정한 전략에 따라 일부 쿼리를 취소하여 해당 메모리를 해제하고, 프로세스에 대해 OOM Killer가 실행되는 것을 방지하는 경우가 많습니다. 이때 쿼리 취소 과정이 멈추어 메모리를 제때 해제하지 못하면 OOM Killer가 실행될 위험이 커질 뿐 아니라, 프로세스 메모리 부족으로 더 많은 쿼리가 취소될 수도 있습니다.

쿼리가 취소된 것으로 확인되었다면, 해당 QueryID를 기준으로 취소 과정에서 멈췄는지 다음과 같이 분석합니다. 먼저 grep {queryID} be/log/be.INFO를 실행하여 Cancel 키워드를 포함하는 첫 번째 로그를 찾습니다. 해당 시점이 쿼리가 취소된 시점입니다. 이어서 deregister query/load memory tracker 키워드를 포함하는 로그를 찾습니다. 해당 시점이 쿼리 취소가 완료된 시점입니다. 결국 OOM Killer가 실행되었고 deregister query/load memory tracker 키워드를 포함하는 로그가 없다면, OOM Killer가 실행될 때까지 쿼리 취소가 완료되지 않았다는 뜻입니다. 일반적으로 쿼리 취소 과정이 3s를 넘으면 취소 과정에서 멈춘 것으로 보며, 쿼리 실행 로그를 추가로 분석해야 합니다.

또한 grep {queryID} be/log/be.INFO를 실행한 후 tasks is being canceled and has not been completed yet 키워드가 포함된 로그가 보이면, 그 뒤에 나오는 QueryID 목록은 Memory GC 실행 시 취소가 진행 중이지만 아직 완료되지 않은 것으로 확인된 쿼리를 나타냅니다. 이때는 해당 쿼리를 건너뛰고 다른 곳에서 메모리를 계속 해제합니다. 이를 통해 Memory GC가 예상대로 동작하는지 판단할 수 있습니다.