인트로스펙션 함수

인트로스펙션 함수 (Introspection Functions)

이 장에서 설명하는 함수들은 쿼리 프로파일링을 위해 ELFDWARF를 들여다보는(introspect) 데 사용할 수 있어요.

참고: 이 함수들은 느리고 보안상 고려 사항이 있을 수 있어요.

인트로스펙션 함수가 제대로 동작하려면:

  • clickhouse-common-static-dbg 패키지를 설치하세요.
  • allow_introspection_functions 설정을 1로 설정하세요. 보안상 이유로 인트로스펙션 함수는 기본적으로 비활성화되어 있어요.

ClickHouse는 프로파일러 보고서를 trace_log 시스템 테이블에 저장해요. 테이블과 프로파일러가 제대로 구성되어 있는지 확인하세요.

출처: 문서

본문

addressToLine

도입: v20.1.0

ClickHouse 서버 프로세스 안의 가상 메모리 주소를 ClickHouse 소스 코드의 파일명과 줄 번호로 변환해요.

참고: 이 함수는 느리고 보안상 고려 사항이 있을 수 있어요.

이 인트로스펙션 함수를 활성화하려면:

  • clickhouse-common-static-dbg 패키지를 설치하세요.
  • 설정 allow_introspection_functions1로 설정하세요.

참고: 이 함수는 비결정적이에요. 같은 인자에 대해 다른 결과를 반환할 수 있어요.

구문 (Syntax)

addressToLine(address_of_binary_instruction)

인자 (Arguments)

  • address_of_binary_instruction — 실행 중인 프로세스 안의 명령어 주소. UInt64

반환 값 (Returned value)

콜론으로 구분된 소스 코드 파일명과 줄 번호를 반환해요. 예: /build/obj-x86_64-linux-gnu/../src/Common/ThreadPool.cpp:199. 디버그 정보를 찾을 수 없으면 바이너리 이름을, 주소가 유효하지 않으면 빈 문자열을 반환해요. String

예시 (Examples)

trace_log 시스템 테이블에서 첫 문자열 선택

SET allow_introspection_functions=1;
SELECT * FROM system.trace_log LIMIT 1 FORMAT Vertical;
-- `trace` 필드는 샘플링 시점의 스택 트레이스를 담고 있다.
Row 1:
──────
event_date:              2019-11-19
event_time:              2019-11-19 18:57:23
revision:                54429
timer_type:              Real
thread_number:           48
query_id:                421b6855-1858-45a5-8f37-f383409d6d72
trace:                   [140658411141617,94784174532828,94784076370703,94784076372094,94784076361020,94784175007680,140658411116251,140658403895439]

단일 주소에 대한 소스 파일명과 줄 번호 얻기

SET allow_introspection_functions=1;
SELECT addressToLine(94784076370703) FORMAT Vertical;
Row 1:
──────
addressToLine(94784076370703): /build/obj-x86_64-linux-gnu/../src/Common/ThreadPool.cpp:199

전체 스택 트레이스에 함수 적용

-- 이 예제의 arrayMap 함수는 trace 배열의 각 요소를 addressToLine 함수로 처리한다.
-- 이 처리 결과는 출력의 trace_source_code_lines 컬럼에서 볼 수 있다.

SELECT
    arrayStringConcat(arrayMap(x -> addressToLine(x), trace), '\n') AS trace_source_code_lines
FROM system.trace_log
LIMIT 1
FORMAT Vertical;
Row 1:
──────
trace_source_code_lines: /lib/x86_64-linux-gnu/libpthread-2.27.so
/usr/lib/debug/usr/bin/clickhouse
/build/obj-x86_64-linux-gnu/../src/Common/ThreadPool.cpp:199
/build/obj-x86_64-linux-gnu/../src/Common/ThreadPool.h:155
/usr/include/c++/9/bits/atomic_base.h:551
/usr/lib/debug/usr/bin/clickhouse
/lib/x86_64-linux-gnu/libpthread-2.27.so
/build/glibc-OTsEL5/glibc-2.27/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:97

addressToLineWithInlines

도입: v22.2.0

addressToLine과 비슷하지만 모든 인라인 함수들을 담은 Array를 반환해요. 그 때문에 addressToLine보다 느려요.

이 인트로스펙션 함수를 활성화하려면:

  • clickhouse-common-static-dbg 패키지를 설치하세요.
  • 설정 allow_introspection_functions1로 설정하세요.

참고: 이 함수는 비결정적이에요. 같은 인자에 대해 다른 결과를 반환할 수 있어요.

구문 (Syntax)

addressToLineWithInlines(address_of_binary_instruction)

인자 (Arguments)

  • address_of_binary_instruction — 실행 중인 프로세스 안의 명령어 주소. UInt64

반환 값 (Returned value)

첫 번째 요소가 콜론으로 구분된 소스 코드 파일명과 줄 번호인 배열을 반환해요. 두 번째, 세 번째 등의 요소는 인라인 함수들의 소스 코드 파일명·줄 번호·함수 이름을 나열해요. 디버그 정보를 찾을 수 없으면 바이너리 이름과 같은 단일 요소 배열을, 주소가 유효하지 않으면 빈 배열을 반환해요. Array(String)

예시 (Examples)

주소에 함수 적용

SET allow_introspection_functions=1;
SELECT addressToLineWithInlines(531055181::UInt64);
┌─addressToLineWithInlines(CAST('531055181', 'UInt64'))─────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ['./src/Functions/addressToLineWithInlines.cpp:98','./build_normal_debug/./src/Functions/addressToLineWithInlines.cpp:176:DB::(anonymous namespace)::FunctionAddressToLineWithInlines::implCached(unsigned long) const'] │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

전체 스택 트레이스에 함수 적용

SET allow_introspection_functions=1;

-- arrayJoin 함수가 배열을 행으로 나눈다.

SELECT
    ta, addressToLineWithInlines(arrayJoin(trace) AS ta)
FROM system.trace_log
WHERE
    query_id = '5e173544-2020-45de-b645-5deebe2aae54';
┌────────ta─┬─addressToLineWithInlines(arrayJoin(trace))───────────────────────────────────┐
│ 365497529 │ ['./build_normal_debug/./contrib/libcxx/include/string_view:252']            │
│ 365593602 │ ['./build_normal_debug/./src/Common/Dwarf.cpp:191']                           │
│ ...       │ ...                                                                          │
│ 531055181 │ ['./src/Functions/addressToLineWithInlines.cpp:98','./build_normal_debug/... │
└───────────┴──────────────────────────────────────────────────────────────────────────────┘

addressToSymbol

도입: v20.1.0

ClickHouse 서버 프로세스 안의 가상 메모리 주소를 ClickHouse 오브젝트 파일의 심볼(symbol)로 변환해요.

참고: 이 함수는 비결정적이에요. 같은 인자에 대해 다른 결과를 반환할 수 있어요.

구문 (Syntax)

addressToSymbol(address_of_binary_instruction)

인자 (Arguments)

  • address_of_binary_instruction — 실행 중인 프로세스 안의 명령어 주소. UInt64

반환 값 (Returned value)

ClickHouse 오브젝트 파일의 심볼, 또는 주소가 유효하지 않으면 빈 문자열. String

예시 (Examples)

trace_log 시스템 테이블에서 첫 문자열 선택

SET allow_introspection_functions=1;
SELECT * FROM system.trace_log LIMIT 1 FORMAT Vertical;
-- `trace` 필드는 샘플링 시점의 스택 트레이스를 담고 있다.
Row 1:
──────
event_date:    2019-11-20
event_time:    2019-11-20 16:57:59
revision:      54429
timer_type:    Real
thread_number: 48
query_id:      724028bf-f550-45aa-910d-2af6212b94ac
trace:         [94138803686098,94138815010911,94138815096522,94138815101224,94138815102091,94138814222988,94138806823642,94138814457211,94138806823642,94138814457211,94138806823642,94138806795179,94138806796144,94138753770094,94138753771646,94138753760572,94138852407232,140399185266395,140399178045583]

단일 주소에 대한 심볼 얻기

SET allow_introspection_functions=1;
SELECT addressToSymbol(94138803686098) FORMAT Vertical;
Row 1:
──────
addressToSymbol(94138803686098): _ZNK2DB24IAggregateFunctionHelperINS_20AggregateFunctionSumImmNS_24AggregateFunctionSumDataImEEEEE19addBatchSinglePlaceEmPcPPKNS_7IColumnEPNS_5ArenaE

전체 스택 트레이스에 함수 적용

SET allow_introspection_functions=1;

-- arrayMap 함수는 trace 배열의 각 요소를 addressToSymbol 함수로 처리한다.
-- 이 처리 결과는 출력의 trace_symbols 컬럼에서 볼 수 있다.

SELECT
    arrayStringConcat(arrayMap(x -> addressToSymbol(x), trace), '\n') AS trace_symbols
FROM system.trace_log
LIMIT 1
FORMAT Vertical;
Row 1:
──────
trace_symbols: _ZNK2DB24IAggregateFunctionHelperINS_20AggregateFunctionSumImmNS_24AggregateFunctionSumDataImEEEEE19addBatchSinglePlaceEmPcPPKNS_7IColumnEPNS_5ArenaE
_ZNK2DB10Aggregator21executeWithoutKeyImplERPcmPNS0_28AggregateFunctionInstructionEPNS_5ArenaE
...

demangle

도입: v20.1.0

심볼을 C++ 함수 이름으로 변환해요. 심볼은 보통 addressToSymbol 함수가 반환해요.

구문 (Syntax)

demangle(symbol)

인자 (Arguments)

  • symbol — 오브젝트 파일의 심볼. String

반환 값 (Returned value)

C++ 함수의 이름, 또는 심볼이 유효하지 않으면 빈 문자열. String

예시 (Examples)

단일 주소에 대한 함수 이름 얻기

SET allow_introspection_functions=1;
SELECT demangle(addressToSymbol(94138803686098)) FORMAT Vertical;
Row 1:
──────
demangle(addressToSymbol(94138803686098)): DB::IAggregateFunctionHelper<DB::AggregateFunctionSum<unsigned long, unsigned long, DB::AggregateFunctionSumData<unsigned long> > >::addBatchSinglePlace(unsigned long, char*, DB::IColumn const**, DB::Arena*) const

전체 스택 트레이스에 함수 적용

SET allow_introspection_functions=1;

-- arrayMap 함수는 trace 배열의 각 요소를 demangle 함수로 처리한다.
-- 이 처리 결과는 출력의 trace_functions 컬럼에서 볼 수 있다.

SELECT
    arrayStringConcat(arrayMap(x -> demangle(addressToSymbol(x)), trace), '\n') AS trace_functions
FROM system.trace_log
LIMIT 1
FORMAT Vertical;
Row 1:
──────
trace_functions: DB::IAggregateFunctionHelper<DB::AggregateFunctionSum<unsigned long, unsigned long, DB::AggregateFunctionSumData<unsigned long> > >::addBatchSinglePlace(unsigned long, char*, DB::IColumn const**, DB::Arena*) const
DB::Aggregator::executeWithoutKeyImpl(char*&, unsigned long, DB::Aggregator::AggregateFunctionInstruction*, DB::Arena*) const
...

isMergeTreePartCoveredBy

도입: v25.6.0

첫 번째 인자의 파트가 두 번째 인자의 파트로 덮이는지 확인하는 함수예요.

구문 (Syntax)

isMergeTreePartCoveredBy(nested_part, covering_part)

인자 (Arguments)

  • nested_part — 예상되는 중첩 파트의 이름. String
  • covering_part — 예상되는 덮는(covering) 파트의 이름. String

반환 값 (Returned value)

덮으면 1, 아니면 0. UInt8

예시 (Examples)

기본 예시

WITH 'all_12_25_7_4' AS lhs, 'all_7_100_10_20' AS rhs
SELECT isMergeTreePartCoveredBy(rhs, lhs), isMergeTreePartCoveredBy(lhs, rhs);
┌─isMergeTreePartCoveredBy(rhs, lhs)─┬─isMergeTreePartCoveredBy(lhs, rhs)─┐
│                                  0 │                                  1 │
└────────────────────────────────────┴────────────────────────────────────┘

logTrace

도입: v20.12.0

서버 로그에 trace 로그 메시지를 출력해요.

이 함수는 상수 인자만 받으므로, 호출은 쿼리 분석 중에 평가되어 그 결과로 대체돼요. 따라서 메시지는 쿼리가 분석되는 동안 한 번만 출력되며, 처리되는 Block마다 출력되지 않아요: 행 수와 설정 max_block_size는 로그에 나타나는 메시지 수에 영향을 주지 않아요.

구문 (Syntax)

logTrace(message)

인자 (Arguments)

  • message — 서버 로그로 출력되는 메시지. const String

반환 값 (Returned value)

항상 0. UInt8

예시 (Examples)

기본 예시

SELECT logTrace('logTrace message');
┌─logTrace('logTrace message')─┐
│                            0 │
└──────────────────────────────┘

mergeTreePartInfo

도입: v25.6.0

MergeTree 파트 이름에서 유용한 값들을 잘라내는 데 도움을 주는 함수예요.

구문 (Syntax)

mergeTreePartInfo(part_name)

인자 (Arguments)

  • part_name — 풀어낼 파트의 이름. String

반환 값 (Returned value)

partition_id, min_block, max_block, level, mutation 하위 컬럼을 가진 Tuple. Tuple

예시 (Examples)

기본 예시

WITH mergeTreePartInfo('all_12_25_7_4') AS info
SELECT info.partition_id, info.min_block, info.max_block, info.level, info.mutation;
┌─info.partition_id─┬─info.min_block─┬─info.max_block─┬─info.level─┬─info.mutation─┐
│ all               │             12 │             25 │          7 │             4 │
└───────────────────┴────────────────┴────────────────┴────────────┴───────────────┘

tid

도입: v20.12.0

현재 Block을 처리하는 스레드의 id를 반환해요.

구문 (Syntax)

tid()

인자 (Arguments)

  • 없음.

반환 값 (Returned value)

현재 스레드 id. UInt64

예시 (Examples)

SELECT tid();
┌─tid()─┐
│  3878 │
└───────┘

더 알아보기 (Learn more)