콘텐츠로 이동

DQL vs 기타 쿼리 언어


들어가며

DQL을 빠르게 이해하고 활용할 수 있도록 돕기 위해, DQL을 세 가지 일반적인 쿼리 언어인 PromQL, LogQL, SQL과 비교합니다.

PromQL은 Prometheus에서 시계열 데이터를 쿼리하기 위한 언어입니다. LogQL은 Grafana Loki를 위한 로그 쿼리 언어로, PromQL의 문법 구조를 참고하여 설계되었으며 PromQL과 작성 방식이 매우 유사합니다. SQL은 우리가 일상적으로 가장 많이 사용하는 범용 쿼리 언어로, 문법 구조가 앞의 두 언어와 크게 다릅니다 (각 데이터베이스마다 약간의 차이는 있지만, 여기서는 MySQL을 기준으로 합니다).

참고

SQL은 강력한 데이터 추가, 삭제, 조회, 수정 기능을 제공하지만, 여기서는 조회 기능만을 비교 대상으로 합니다.

DQL 초기에는 PromQL과 유사한 문법 구조를 가졌지만, 비즈니스가 지속적으로 확장됨에 따라 DQL은 점차 다양한 쿼리 기능으로 발전했습니다. DQL은 PromQL의 기본 문법 구조를 통합하는 동시에 SQL 문의 일부 문법 구조와 의미 표현을 참고하여, 사용자가 더 복잡한 쿼리를 더 쉽게 작성할 수 있도록 설계되었습니다.

아래에서는 다음 측면에서 각 쿼리 언어의 차이점을 설명합니다.

  • 기본 문법 구조
  • 지원하는 일반적인 사전 정의 함수
  • 일반적인 쿼리 작성 방식

기본 문법 구조

쿼리 언어 기본 구조
PromQL 메트릭 {조건 필터 목록} [시작 시간:종료 시간]
LogQL {stream-selector} log-pipeline
SQL SELECT <column-clause> <FROM-clause> <WHERE-clause> <GROUP-BY-clause> ...
DQL namespace::메저먼트:(column-clause) [time-range-clause] { WHERE-clause } GROUP-BY-clause ORDER-BY-clause

PromQL

Prometheus에서 관련 메트릭은 개별 형태로 구성됩니다. 쿼리 시 해당 메트릭을 직접 조회할 수 있습니다. 예:

http_requests_total{environment="prometheus", method!="GET"}

여기서는 메트릭 http_requests_total을 조회하고, label 조건(environmentmethod)을 지정하여 데이터를 필터링합니다.

참고

PromQL에서는 여기서의 label 조건을 Label Matchers라고 합니다. 간단히 WHERE 조건 필터로 이해할 수 있습니다.

LogQL

이름에서 알 수 있듯이 LogQL은 주로 로그 내용 쿼리에 사용됩니다. 예:

{container="query-frontend", namespace="loki-dev"}
    |= "metrics.go"
    | logfmt
    | duration > 10s and throughput_mb < 500

여기서 {...} 안의 부분을 LogQL에서는 Stream Selector라고 하며, 데이터 쿼리 범위를 지정합니다 (SQL의 FROM ... 부분과 유사). 후반부는 Log Pipeline이라고 하며, 주로 로그 정보의 추출 및 필터링을 처리합니다.

여기에서 LogQL의 {...}는 PromQL의 Label Matchers와 동일하게, WHERE 조건 필터로 이해할 수 있습니다.

SQL

가장 익숙한 쿼리 언어인 SQL로 위 두 가지 효과를 얻으려면 다음과 같이 간단히 표현할 수 있습니다 (저장 구조가 다르므로 여기서는 대략적인 의미만 표현합니다).

SELECT * FROM `loki-dev`
    WHERE container="query-frontend" AND
    duration > 10s AND
    throughput_mb < 500

DQL

DQL은 기본적으로 쿼리 변환기로, 백엔드에서 데이터 저장 및 구성을 직접 관리하지 않습니다. 따라서 이론적으로 MySQL, Oracle, ES, Redis 등의 정보 데이터 저장소, HBASE, S3, OSS 등의 파일 저장소 등 모든 유형의 스토리지 엔진을 지원할 수 있습니다. 현재 DQL은 주로 다음 유형의 데이터를 쿼리하는 데 사용됩니다.

  • 시계열 데이터
  • 로그 데이터
  • 객체 데이터
  • 애플리케이션 성능 모니터링(APM) 데이터
  • 실제 사용자 모니터링(RUM) 데이터
  • 주요 이벤트 데이터
  • ...

예:

metric::cpu:(usage_system, usage_user) { usage_idle > 0.9 } [2d:1d:1h] BY hostname

여기서 metric은 시계열 데이터를 쿼리하도록 지정하고 (MySQL의 DB로 간단히 이해 가능), cpu는 그 안의 하나의 메저먼트입니다 (MySQL의 Table과 유사). 그리고 두 필드 usage_systemusage_user를 조회하도록 지정합니다. 다음으로 {...}는 필터 조건을 나타내고, 마지막으로 [...]는 쿼리 시간 범위를 나타냅니다. 그제부터 어제까지의 시간 범위를 1시간 간격으로 집계합니다.

더 많은 예시:

# K8s의 pod 객체(object) 조회
object::kubelet_pod:(name, age) { cpu_usage > 30.0 } [10m] BY namespace

# my_service 애플리케이션의 로그(message 필드) 조회
logging::my_service:(message) [1d]

# 애플리케이션 성능 추적(T는 tracing을 의미)에서 duration > 1000us인 span 데이터를 조회하고, operation별로 그룹화
T::my_service { duration > 1000 } [10m] BY operation

비교

기본 기능 비교

쿼리 언어 주요 영역 시계열 쿼리 로그 쿼리 시간 범위 조회 group by 집계
PromQL Prometheus 메트릭 쿼리 지원 미지원 지원 지원
LogQL 로그 쿼리 로그에서 메트릭 생성 지원 지원 지원 지원
SQL 범용 쿼리 언어 일부 데이터베이스
시계열 저장 지원
부적합 지원 지원
DQL Guance 전체 플랫폼 데이터 쿼리 지원 지원 지원 지원

지원 도구

쿼리 언어 주석 방식 HTTP API Pipeline 처리 명령줄
PromQL # 한 줄 주석 지원 미지원 promql-cli
LogQL # 한 줄 주석 지원 지원 logcli
SQL -- 한 줄 주석
또는 /* 여러 줄 주석 */
미지원 미지원 다양한 SQL 클라이언트 (자세한 설명 생략)
DQL # 한 줄 주석 지원 미지원 (DataKit에서 사전 처리됨) DataKit 설치
쿼리 실행

데이터 처리 함수 지원 현황

일반적인 쿼리문 작성 방식 비교

일반 데이터 쿼리 및 필터링

# LogQL
{ cluster="ops-tools1", namespace="dev", job="query-frontend"}
  |= "metrics.go"
  !="out of order"
  | logfmt
  | duration > 30s or status_code!="200"

# PromQL (PromQL은 일반적인 의미의 OR 필터링을 지원하지 않는 것으로 보임)
http_requests_total{ cluster='ops-tools1', job!='query=frontend', duration > 30s }

# SQL
SELECT * FROM dev
  WHERE cluster='ops-tools' AND
  job='query=frontend' AND
  (duration > 30000000000 OR stataus_code != 200)

# DQL: 문장 구조에서 볼 수 있듯이 DQL의 의미 구조는 SQL과 유사합니다.
L::dev {
  cluster='ops-tools',
  job='query=frontend',
  message != match("out of order")
  (duraton > 30s OR stataus_code != 200) # DQL은 중첩 구조 필터링을 지원합니다.
}

다양한 DQL 문장 작성 방식:

# where-clause는 AND로 연결할 수 있으며, AND는 ','와 의미가 동일합니다.
L::dev {
  cluster='ops-tools' AND
  job='query=frontend' AND
  message != match("out of order") AND
  (duraton > 30s OR stataus_code != 200)}

# AS 별칭 지원 / 한글 변수 지원
metric::cpu:(usage_system AS 시스템 사용량, usage_user AS 사용자 사용량)

# where-clause는 array-list IN 필터링을 지원합니다.
L::dev {
  cluster='ops-tools' AND
  job IN [ 'query=frontend', 'query=backend'] AND
  message != match("out of order") AND
  (duraton > 30s OR stataus_code != 200)
}

# base64 값 전달 지원: 복잡한 문자열(예: 여러 줄)의 경우 번거로운 이스케이프를 피할 수 있습니다.
T::dev {
  cluster='ops-tools' AND
  resourec IN [
    'some-raw-string', # 일반 문자열
    b64'c2VsZWN0ICoKZnJvbSBhYmMKd2hlcmUgeCA+IDAK' # base64 문자열
  ]
}

집계 쿼리 및 필터링

# LogQL
sum by (org_id) ({source="ops-tools",container="app-dev"} |= "metrics.go" | logfmt | unwrap bytes_processed [1m])

# PromQL
histogram_quantile(0.9, sum by (job, le) (rate(http_request_duration_seconds_bucket[10m])))

# DQL (참고: ops-tools 양쪽에 ``를 붙여야 합니다. 그렇지 않으면 뺄셈 표현식으로解析됩니다.)
L::`ops-tools`:(bytes_processed) {filename = "metrics.go", container="app-dev"} [2m] BY sum(orig_id)

데이터 현황 조회

# LogQL/PromQL: 아직 유사한 쿼리 기능을 찾을 수 없습니다.

# MySQL
show tables;
show databases;

# DQL
show_measurement()    # 시계열 메저먼트 목록 조회
show_object_source()  # 객체 분류 목록 조회
show_rum_source()     # RUM 데이터 분류 목록 조회
show_logging_source() # 로그 분류 목록 조회

정리

위 내용은 몇 가지 일반적인 쿼리 언어에 대한 기본적인 소개를 제공했습니다. 각 언어는 특정한 사용 사례를 가지며, 기능 차이가 뚜렷합니다. DQL의 설계 목표는 혼합 저장소 쿼리 솔루션을 제공하는 것이며, 이는 다른 언어와 본질적으로 구별됩니다. DQL은 독립적인 스토리지 엔진이 없지만, 확장성은 다른 언어를 훨씬 능가하며, 혼합 저장소 쿼리라는 포지셔닝에 부합합니다.

현재 DQL은 활발히 개발 및 개선 중이며, 기능과 성능 모두 향상 여지가 큽니다. Guance에서는 모든 데이터 쿼리에 DQL이 전면적으로 적용되어 있으며, 그 기능, 성능 및 안정성은 오랜 시간 검증을 거쳤습니다. Guance 제품의 지속적인 발전과 함께 DQL도 계속 진화하여 제품과 개발자의 요구를 충족시킬 것입니다.

문서 평가

이 페이지가 도움이 되었나요?