system.user_query_log 시스템 테이블
system.user_query_log 시스템 테이블
system.user_query_log 는 현재 사용자에게 자신의 쿼리 로그 레코드를 보여주는 테이블이에요. 사용자가 다른 사람의 쿼리에 접근하지 않고도 자신의 쿼리를 검사할 수 있게 해줘요.
출처: 문서
본문
Description
현재 사용자에게 자신의 쿼리 로그 레코드를 보여줘요. query_log.database 및 query_log.table 서버 설정으로 구성된 쿼리 로그 테이블(기본값 system.query_log)을 읽고 시작 사용자가 currentUser() 와 같은 행만 반환해요(시작 사용자는 initial_user 가 설정되면 그 값, 그렇지 않으면 user 값이에요).
쿼리 로그 테이블 자체와 달리 system.user_query_log 는 어떤 grant 없이도 읽을 수 있어서, 사용자는 다른 사람의 쿼리에 대한 접근 권한 없이도 자신의 쿼리를 검사할 수 있어요.
이것은 쿼리 로그가 로컬에 저장된 경우에만 지원돼요. query_log.engine 이 Distributed 로 구성되었거나 다른 서버에 읽기를 위임하는 다른 엔진인 경우, system.user_query_log 는 그것을 읽기를 거부하고 예외를 던져요. 필요한 접근 검사가 ClickHouse 프로토콜 서버 경계를 넘어 시행될 수 없기 때문이에요. 그 경우 query_log.enable_user_query_log = 0 으로 테이블을 비활성화해요.
가용성(Availability)
system.user_query_log 는 query_log.enable_user_query_log 서버 설정이 활성화된 경우에만 첨부되는데, 이것이 기본값이에요. 설정이 0 이면 테이블이 존재하지 않고 쿼리는 UNKNOWN_TABLE 오류로 실패해요.
query_log.enable_user_query_log 가 활성화되었지만 기반 쿼리 로그가 구성되지 않았거나 그 테이블이 아직 생성되지 않았다면 system.user_query_log 는 존재하지만 비어 있어요.
쿼리 로그의 파티션 및 키 열(event_date, event_time, query_start_time, query_id, type 및 유사한 스칼라 열)에 대한 조건은 상수와 비교되면 기반 쿼리 로그 테이블로 푸시 다운되어, 아래 예제 같은 일반 조회는 파티션 프루닝을 유지하고 보관된 전체 로그를 스캔하지 않아요.
이 테이블을 제공하는 ClickHouse 버전으로 업그레이드하기 전에 system.user_query_log 라는 이름의 테이블이 만들어졌다면, 기존 테이블이 이름이 바뀌거나 drop되거나 query_log.enable_user_query_log 가 0 으로 설정될 때까지 서버가 시작되지 않아요.
Columns
-
hostname(String) — 쿼리를 실행한 서버의 호스트 이름이에요. -
clickhouse_version(String) — 이 행을 만든 ClickHouse 서버의 버전이에요. -
system_processor(String) — 이 행을 만든 ClickHouse 서버의 CPU 아키텍처예요. -
type(Enum8(‘QueryStart’ = 1, ‘QueryFinish’ = 2, ‘ExceptionBeforeStart’ = 3, ‘ExceptionWhileProcessing’ = 4)) — 쿼리 실행 중 발생한 이벤트의 유형이에요. 값:QueryStart— 쿼리 실행의 성공적인 시작,QueryFinish— 쿼리 실행의 성공적인 종료,ExceptionBeforeStart— 쿼리 실행 시작 전 예외,ExceptionWhileProcessing— 쿼리 실행 중 예외. -
event_date(Date) — 쿼리 시작 날짜예요. -
event_time(DateTime) — 쿼리 시작 시간이에요. -
event_time_microseconds(DateTime64(6)) — 마이크로초 정밀도의 쿼리 시작 시간이에요. -
query_start_time(DateTime) — 쿼리 실행 시작 시간이에요. -
query_start_time_microseconds(DateTime64(6)) — 마이크로초 정밀도의 쿼리 실행 시작 시간이에요. -
query_duration_ms(UInt64) — 쿼리 실행 시간(밀리초)이에요. -
read_rows(UInt64) — 쿼리에 참여한 모든 테이블과 테이블 함수에서 읽은 총 행 수예요. 일반 하위 쿼리, IN 및 JOIN용 하위 쿼리를 포함해요. 분산 쿼리의 경우 read_rows 는 모든 복제본에서 읽은 총 행 수를 포함해요. 각 복제본은 자신의 read_rows 값을 보내고 쿼리 시작자 서버가 받은 값과 로컬 값을 모두 합산해요. 캐시 볼륨은 이 값에 영향을 주지 않아요. -
read_bytes(UInt64) — 쿼리에 참여한 모든 테이블과 테이블 함수에서 읽은 총 바이트 수예요. 일반 하위 쿼리, IN 및 JOIN용 하위 쿼리를 포함해요. 분산 쿼리의 경우 read_bytes 는 모든 복제본에서 읽은 총 행 수를 포함해요. 각 복제본은 자신의 read_bytes 값을 보내고 쿼리 시작자 서버가 받은 값과 로컬 값을 모두 합산해요. 캐시 볼륨은 이 값에 영향을 주지 않아요. -
written_rows(UInt64) — 쿼리가 쓴 행 수예요. 파이프라인에 의해 트리거된 다운스트림 삽입(예: 연결된 구체화된 뷰)이 쓴 행도 포함해요. 동기 삽입의 경우query_kind=Insert항목에 기록되고, 비동기 삽입의 경우query_kind=AsyncInsertFlush항목에 기록되며 클라이언트 측Insert항목은 클라이언트로부터 받은 행만 기록해요. 행을 쓰지 않는 쿼리는 0이에요. -
written_bytes(UInt64) — 쿼리가 쓴 바이트 수(압축되지 않음)예요. 파이프라인에 의해 트리거된 다운스트림 삽입이 쓴 바이트도 포함해요. 동기 삽입의 경우query_kind=Insert항목에 기록되고, 비동기 삽입의 경우query_kind=AsyncInsertFlush항목에 기록되며 클라이언트 측Insert항목은 클라이언트로부터 받은 바이트만 기록해요. 데이터를 쓰지 않는 쿼리는 0이에요. -
result_rows(UInt64) — SELECT 쿼리 결과의 행 수 또는 삽입이 쓴 행 수예요. 동기 삽입의 경우query_kind=Insert항목에 파이프라인이 트리거한 다운스트림 삽입이 쓴 행이 포함되고, 비동기 삽입의 경우 해당 다운스트림 행이query_kind=AsyncInsertFlush항목에 기록되며 클라이언트 측Insert항목은 클라이언트로부터 받은 행만 기록해요. -
result_bytes(UInt64) — 쿼리 결과를 저장하는 데 사용된 RAM 볼륨(바이트)이에요. -
memory_usage(UInt64) — 쿼리의 메모리 소비예요. -
current_database(String) — 현재 데이터베이스의 이름이에요. -
query(String) — 쿼리 문자열이에요. -
formatted_query(String) — 포맷된 쿼리 문자열이에요. -
normalized_query_hash(UInt64) — 리터럴 값만 다른 쿼리에는 동일한 숫자 해시 값이에요. -
query_kind(String) — 쿼리 유형이에요. -
databases(Array(String)) — 쿼리에 있는 데이터베이스 이름이에요. -
tables(Array(String)) — 쿼리에 있는 테이블 이름이에요. -
columns(Array(String)) — 쿼리에 있는 열 이름이에요. -
partitions(Array(String)) — 쿼리에 있는 파티션 이름이에요. -
projections(Array(String)) — 쿼리 실행 중 사용된 프로젝션 이름이에요. -
views(Array(String)) — 쿼리에 있는 (구체화된 또는 라이브) 뷰 이름이에요. -
exception_code(Int32) — 예외 코드예요. -
exception(String) — 예외 메시지예요. -
stack_trace(String) — 스택 트레이스예요. 쿼리가 성공적으로 완료되면 빈 문자열이에요. -
is_initial_query(UInt8) — 쿼리가 초기 쿼리인지 여부예요. 가능한 값: 1 — 초기(최상위) 쿼리, 0 — 다른 쿼리에 의해 시작된 자식 쿼리(분산 실행을 위한 쿼리와 내부 하위 쿼리 포함). -
connection_address(IPv6) — 연결이 만들어진 클라이언트 IP 주소예요. 프록시를 통해 연결할 때는 프록시의 주소가 돼요. -
connection_port(UInt16) — 연결이 만들어진 클라이언트 포트예요. 프록시를 통해 연결할 때는 프록시의 포트가 돼요. -
user(String) — 현재 쿼리를 시작한 사용자의 이름이에요. -
query_id(String) — 쿼리 ID예요. -
address(IPv6) — 쿼리를 만드는 데 사용된 IP 주소예요. 프록시를 통해 연결하고auth_use_forwarded_address가 설정된 경우 프록시 대신 클라이언트의 주소가 돼요. -
port(UInt16) — 쿼리를 만드는 데 사용된 클라이언트 포트예요. 프록시를 통해 연결하고auth_use_forwarded_address가 설정된 경우 프록시 대신 클라이언트의 포트가 돼요. -
initial_user(String) — 동일한 쿼리 체인에서 초기 쿼리를 실행한 사용자의 이름이에요. -
initial_query_id(String) — 동일한 쿼리 체인에서 초기 쿼리의 ID예요. -
initial_address(IPv6) — 동일한 쿼리 체인에서 초기 쿼리가 시작된 IP 주소예요. -
initial_port(UInt16) — 동일한 쿼리 체인에서 초기 쿼리가 시작된 클라이언트 포트예요. -
initial_query_start_time(DateTime) — 동일한 쿼리 체인에서 초기 쿼리의 시작 시간이에요. -
initial_query_start_time_microseconds(DateTime64(6)) — 동일한 쿼리 체인에서 초기 쿼리의 시작 시간(마이크로초 정밀도)이에요. -
authenticated_user(String) — 세션에서 인증된 사용자의 이름이에요. -
interface(Enum8(‘Unknown’ = 0, ‘TCP’ = 1, ‘HTTP’ = 2, ‘gRPC’ = 3, ‘MySQL’ = 4, ‘PostgreSQL’ = 5, ‘Local’ = 6, ‘TCP_Interserver’ = 7, ‘Prometheus’ = 8, ‘Background’ = 9, ‘ArrowFlight’ = 10)) — 클라이언트가 보고한 대로 쿼리가 시작된 인터페이스예요. 보고된 인터페이스가 이 서버가 인식하는 것이 아니면Unknown이에요. -
is_secure(UInt8) — 쿼리가 보안 인터페이스를 통해 실행되었는지 여부를 나타내는 플래그예요. -
os_user(String) — clickhouse-client를 실행하는 운영체제 사용자 이름이에요. -
client_hostname(String) — clickhouse-client 또는 다른 TCP 클라이언트가 실행되는 클라이언트 머신의 호스트 이름이에요. -
client_name(String) — clickhouse-client 또는 다른 TCP 클라이언트 이름이에요. -
client_agent(String) — 클라이언트를 호출한 AI 코딩 에이전트(예:claude-code,cursor)로, 환경 변수에서 감지돼요. 에이전트가 감지되지 않으면 비어 있어요. -
client_revision(UInt32) — clickhouse-client 또는 다른 TCP 클라이언트의 리비전이에요. -
client_version_major(UInt32) — clickhouse-client 또는 다른 TCP 클라이언트의 메이저 버전이에요. -
client_version_minor(UInt32) — clickhouse-client 또는 다른 TCP 클라이언트의 마이너 버전이에요. -
client_version_patch(UInt32) — clickhouse-client 또는 다른 TCP 클라이언트 버전의 패치 구성 요소예요. -
script_query_number(UInt32) — clickhouse-client용 여러 쿼리가 있는 스크립트에서의 쿼리 번호예요. -
script_line_number(UInt32) — clickhouse-client용 여러 쿼리가 있는 스크립트에서 쿼리 시작의 줄 번호예요. -
http_method(Enum8(‘UNKNOWN’ = 0, ‘GET’ = 1, ‘POST’ = 2, ‘OPTIONS’ = 3, ‘PUT’ = 4, ‘DELETE’ = 5, ‘HEAD’ = 6)) — 쿼리를 시작한 HTTP 메서드예요. 쿼리가 HTTP로 도착하지 않았거나 보고된 메서드가 이 서버가 인식하는 것이 아니면UNKNOWN이에요. -
http_user_agent(String) — HTTP 쿼리에서 전달된 HTTP 헤더 UserAgent예요. -
http_referer(String) — HTTP 쿼리에서 전달된 HTTP 헤더 Referer예요(쿼리를 만드는 페이지의 절대 또는 부분 주소 포함). -
forwarded_for(String) — HTTP 쿼리에서 전달된 HTTP 헤더 X-Forwarded-For예요. -
quota_key(String) — quotas 설정에 지정된 쿼터 키예요(keyed 참고). -
distributed_depth(UInt64) — 쿼리가 서버 간에 전달된 횟수예요. -
revision(UInt32) — ClickHouse 리비전이에요. -
http_handler_name(String) — 쿼리를 호출한 SQL 정의 HTTP 핸들러(CREATE HANDLER)의 이름이에요. 그러한 핸들러를 통해 호출되지 않았으면 비어 있어요. -
http_request_url(String) — 쿼리를 호출한 HTTP 요청 경로(쿼리 문자열 제외)예요. 민감한 요청 파라미터가 유지되지 않도록 쿼리 문자열은 생략돼요. HTTP가 아닌 쿼리는 비어 있어요. -
log_comment(String) — 로그 설명(comment)이에요. max_query_size 보다 길지 않은 임의 문자열로 설정할 수 있어요. 정의되지 않았으면 빈 문자열이에요. -
thread_ids(Array(UInt64)) — 쿼리 실행에 참여하는 스레드 ID예요. 이 스레드들은 동시에 실행되지 않았을 수 있어요. -
peak_threads_usage(UInt64) — 쿼리를 실행하는 동시 스레드의 최대 수예요. -
ProfileEvents(Map(String, UInt64)) — 다양한 메트릭을 측정하는 ProfileEvents 예요. 이에 대한 설명은 system.events 테이블에서 찾을 수 있어요. -
Settings(Map(String, String)) — 클라이언트가 쿼리를 실행할 때 변경된 설정이에요. 설정 변경 로깅을 활성화하려면 log_query_settings 파라미터를 1로 설정해요. -
used_aggregate_functions(Array(String)) — 쿼리 실행 중 사용된 집계 함수의 정식 이름이에요. -
used_aggregate_function_combinators(Array(String)) — 쿼리 실행 중 사용된 집계 함수 컴비네이터의 정식 이름이에요. -
used_database_engines(Array(String)) — 쿼리 실행 중 사용된 데이터베이스 엔진의 정식 이름이에요. -
used_data_type_families(Array(String)) — 쿼리 실행 중 사용된 데이터 타입 계열의 정식 이름이에요. -
used_dictionaries(Array(String)) — 쿼리 실행 중 사용된 딕셔너리의 정식 이름이에요. -
used_formats(Array(String)) — 쿼리 실행 중 사용된 포맷의 정식 이름이에요. -
used_functions(Array(String)) — 쿼리 실행 중 사용된 함수의 정식 이름이에요. -
used_storages(Array(String)) — 쿼리 실행 중 사용된 스토리지의 정식 이름이에요. -
used_table_functions(Array(String)) — 쿼리 실행 중 사용된 테이블 함수의 정식 이름이에요. -
used_executable_user_defined_functions(Array(String)) — 쿼리 실행 중 사용된 실행 가능한 사용자 정의 함수의 정식 이름이에요. -
used_sql_user_defined_functions(Array(String)) — 쿼리 실행 중 사용된 SQL 사용자 정의 함수의 정식 이름이에요. -
used_row_policies(Array(String)) — 쿼리 실행 중 사용된 행 정책 이름 목록이에요. -
used_privileges(Array(String)) — 쿼리 실행 중 성공적으로 확인된 권한이에요. -
missing_privileges(Array(String)) — 쿼리 실행 중 누락된 권한이에요. -
used_number_of_joins(UInt64) — 이 쿼리에 대해 실행된 물리적 조인 수예요. 파이프라인이 빌드될 때 수집되므로 모든 최적화 후 남은 조인을 반영하며, 쿼리 텍스트의 JOIN 절 수가 아니에요. 조인은 중첩이 얼마나 깊든지 간에 계산돼요. 실행 없이 파이프라인을 빌드하는 쿼리(예: EXPLAIN PIPELINE)는 설명하는 쿼리의 조인을 보고해요. 일부 파이프라인은 단일 쿼리가 실행되는 동안 두 번 이상 조립되지만 그러한 파이프라인의 조인은 여전히 한 번 계산되므로, 이 숫자는 파이프라인이 조립된 횟수가 아니라 쿼리를 기술해요. -
used_join_algorithms(Array(String)) — used_number_of_joins 에 계산된 조인의 알고리즘이에요: ‘HASH’, ‘PARALLEL_HASH’, ‘GRACE_HASH’, ‘PARTIAL_MERGE’, ‘FULL_SORTING_MERGE’, ‘PARALLEL_FULL_SORTING_MERGE’, ‘IE_JOIN’, ‘DIRECT’, ‘PASTE’ 및 ‘CONSTANT’, 정렬되고 중복 제거되어 여러 조인이 공유하는 알고리즘은 한 번만 나타나요. 이것은 각 조인을 실행하기 위해 선택된 알고리즘이며 join_algorithm 설정이 허용하는 알고리즘은 아니에요. 실행 중간에 알고리즘이 다른 것으로 교체될 수 있으며, 그 경우 둘 다 보고돼요. -
used_join_kinds(Array(String)) — used_number_of_joins 에 계산된 조인의 종류로, 조인당 하나의 요소라서 여러 조인이 공유하는 종류는 여러 번 나타나요. 요소는 실행 순서가 아닌 정렬되어 있어요. 각 종류는 실행된 것이며, 옵티마이저가 조인의 양쪽을 바꿔 실행하여 LEFT를 RIGHT로 전환할 수 있으므로 쿼리 텍스트와 다를 수 있어요. -
used_join_strictness(Array(String)) — used_number_of_joins 에 계산된 조인의 엄격성으로, 조인당 하나의 요소이며 used_join_kinds 와 같은 순서예요. -
spilled_to_disk(Array(String)) — 쿼리 실행 중 디스크의 임시 파일에 데이터를 쓴(외부 메모리 처리) 연산자로, 정렬되고 중복 제거돼요. 빈 배열은 쿼리가 완전히 메모리에서 실행되었음을 의미해요. -
transaction_id(Tuple(UInt64, UInt64, UUID, Int64)) — 이 쿼리가 실행된 범위의 트랜잭션 식별자예요. -
query_cache_usage(Enum8(‘Unknown’ = 0, ‘None’ = 1, ‘Write’ = 2, ‘Read’ = 3)) — 쿼리 실행 중 쿼리 캐시 사용이에요. 값: ‘Unknown’ = 상태를 알 수 없음, ‘None’ = 쿼리 결과가 쿼리 결과 캐시에 쓰이지도 읽히지도 않음, ‘Write’ = 쿼리 결과가 쿼리 결과 캐시에 쓰여짐, ‘Read’ = 쿼리 결과가 쿼리 결과 캐시에서 읽힘. -
asynchronous_read_counters(Map(String, UInt64)) — 비동기 읽기 메트릭이에요. -
is_internal(UInt8) — 내부적으로 실행되는 보조 쿼리인지 여부를 나타내요.
별칭(Aliases):
-
ProfileEvents.Names—mapKeys(ProfileEvents)의 별칭이에요. -
ProfileEvents.Values—mapValues(ProfileEvents)의 별칭이에요. -
Settings.Names—mapKeys(Settings)의 별칭이에요. -
Settings.Values—mapValues(Settings)의 별칭이에요.
Example
SELECT
query_start_time,
query_duration_ms,
query
FROM system.user_query_log
ORDER BY query_start_time DESC
LIMIT 10;