ClickHouse SQL 문법 심층 탐구

ClickHouse는 고성능 컬럼형 데이터베이스 관리 시스템으로, SQL 표준을 준수하면서도 분석 작업에 최적화된 독자적인 확장 기능을 제공합니다. 이 문서는 ClickHouse의 SQL 구문 체계를 심도 있게 다루어, 개발자들이 더욱 효과적으로 쿼리 언어를 활용할 수 있도록 돕습니다.

  1. 구문 분석 메커니즘 ClickHouse는 쿼리 유형에 따라 두 가지 파서(Parser)를 사용하여 최적화된 처리를 수행합니다.

  2. 전체 SQL 파서: INSERT 쿼리의 데이터 부분(values)을 제외한 모든 SQL 쿼리를 처리하는 재귀 하향식 파서입니다.

  3. 데이터 형식 파서: INSERT 문에 포함된 대량의 데이터 부분을 빠르게 스트리밍 방식으로 분석합니다.

일반적인 INSERT 문 처리 예시:

INSERT INTO product_sales VALUES (10, 'Smartphone', 50), (11, 'Smartwatch', 30);

이 쿼리에서 INSERT INTO product_sales VALUES 부분은 전체 SQL 파서에 의해 처리되고, 데이터 부분인 (10, 'Smartphone', 50), (11, 'Smartwatch', 30)은 데이터 형식 파서가 담당합니다. 특정 설정(input_format_values_interpret_expressions)을 통해 데이터 부분도 강제로 전체 SQL 파서를 사용하게 할 수 있습니다.

  1. 기본 구문 요소 2.1. 공백 및 주석 SQL 구문 내에서 공백(띄어쓰기, 탭, 줄 바꿈 등)은 자유롭게 사용될 수 있어 가독성을 높입니다. 주석은 다음 세 가지 방식으로 작성할 수 있습니다:
  • SQL 표준 스타일: -- 한 줄 주석
  • Shell 스타일: # 한 줄 주석
  • C 스타일: /* 여러 줄 주석 */

2.2. 키워드 처리 ClickHouse의 키워드 처리 규칙은 다음과 같습니다:

  • 대소문자 불감(Case-Insensitive): SELECT, FROM, WHERE와 같은 SQL 표준 키워드는 대소문자를 구분하지 않습니다.
  • 대소문자 구분(Case-Sensitive): toDate, sum과 같은 함수 이름 등 ClickHouse 고유의 일부 요소는 대소문자를 구분할 수 있습니다.
  • 비예약 키워드(Non-Reserved Keywords): 특정 문맥에서만 키워드로 작동하며, 다른 문맥에서는 일반 식별자로 사용될 수 있는 키워드도 존재합니다.

2.3. 식별자 규칙 식별자는 데이터베이스, 테이블, 컬럼 등의 객체 이름을 지정할 때 사용됩니다.

  • 비인용 식별자(Unquoted Identifiers): 알파벳, 숫자, 밑줄(_)로 시작하며 이어지는 문자도 이들과 동일한 규칙을 따르는 경우 사용합니다 (정규식 ^[a-zA-Z_][0-9a-zA-Z_]*$와 일치).
  • 인용 식별자(Quoted Identifiers): 공백, 특수 문자, 예약어 등을 포함하는 식별자는 이중 따옴표(") 또는 역따옴표(`)로 묶어서 사용해야 합니다.

예시:

SELECT "제품 이름", `재고_수량` FROM `판매_기록`;
  1. 리터럴 상세 3.1. 문자열 리터럴 문자열 리터럴은 반드시 작은따옴표(')로 묶어야 합니다.
  • 작은따옴표 이스케이프: 문자열 내 작은따옴표를 포함하려면 ''와 같이 두 번 반복하거나 \'와 같이 백슬래시로 이스케이프할 수 있습니다. 예: 'It''s a good day.' → "It's a good day."
  • 백슬래시 이스케이프: \n(줄 바꿈), \t(탭)과 같은 표준 백슬래시 이스케이프 시퀀스를 지원합니다.

3.2. 숫자 리터럴 ClickHouse는 다양한 숫자 표현을 지원합니다.

  • 정수: 123, 1_000_000 (밑줄은 가독성을 위해 무시됨)
  • 부동소수점: 3.14, 6.02e23
  • 특수 값: inf (무한대), nan (숫자 아님)
  • 진법 표현:
  • 16진수: 0xDEADBEEF
  • 2진수: 0b1101

3.3. 복합 타입 리터럴

  • 배열: [100, 200, 300]
  • 튜플: (true, 'success', 1.23)

3.4. NULL 값 처리

  • NULL 값은 반드시 Nullable 데이터 타입이 지정된 컬럼에만 저장할 수 있습니다.
  • NULL이 포함된 대부분의 연산 결과는 NULL이 됩니다.
  • NULL 값의 존재 여부는 IS NULL 또는 IS NOT NULL 연산자를 사용하여 확인할 수 있습니다.

3.5. Heredoc 구문 원본 서식을 그대로 유지하는 여러 줄 문자열을 정의할 때 사용됩니다.

SELECT $report_query$
  SELECT event_date, COUNT(DISTINCT user_id) AS unique_users
  FROM user_activity
  WHERE event_date >= '2023-01-01'
  GROUP BY event_date
  ORDER BY event_date DESC
$report_query$;

$report_query$와 같은 식별자는 임의로 지정할 수 있습니다.

  1. 고급 기능 4.1. 쿼리 매개변수화 쿼리 매개변수화는 쿼리의 재사용성과 보안을 향상시킵니다.
  • SET 명령어로 매개변수를 정의합니다.
  • 쿼리 내에서 {parameter_name:DataType} 형식으로 사용하며, 지정된 데이터 타입으로 자동 변환됩니다.
-- 최소 판매액 매개변수 정의
SET param_min_sales_amount = 5000;

-- 정의된 매개변수 사용
SELECT item_name, total_sales FROM sales_summary 
WHERE total_sales >= {min_sales_amount:UInt64};

4.2. 함수 호출 구문 ClickHouse는 다양한 함수를 지원합니다.

  • 표준 함수: now() (현재 시각), toDate(timestamp_col) (날짜로 변환)
  • 집계 함수: sum(amount) (합계), count() (개수)
  • 매개변수화된 집계 함수: quantile(0.99)(value_col) (99번째 백분위수), uniqExact(city_name) (정확한 고유값 개수)

4.3. 연산자 우선순위 ClickHouse는 SQL 연산자를 내부적으로 해당하는 함수 호출로 변환하여 처리합니다. 이는 표준 수학 연산 우선순위를 따르며, 예를 들어 1 + 2 * 3plus(1, multiply(2, 3))와 같이 변환되어 계산됩니다.

  1. 표현식 및 별칭 표현식은 식별자, 리터럴, 함수 호출, 서브쿼리 등의 조합으로 구성됩니다. AS 키워드를 사용하여 표현식의 결과나 컬럼에 별칭(Alias)을 부여할 수 있습니다. 이는 쿼리의 가독성을 높이고 복잡한 표현식을 단순화하는 데 유용합니다.
SELECT
  item_price * quantity_sold AS total_revenue,
  toYYYYMMDD(transaction_time) AS transaction_day
FROM order_details;
  1. 권장 활용 방안
  • 대량 INSERT 성능: 대규모 데이터 삽입 시 VALUES 구문을 활용하면 효율성을 극대화할 수 있습니다.
  • 식별자 명명: 특별한 이유가 없다면 인용 부호 없는 일반 식별자를 사용하여 쿼리를 간결하게 유지하는 것이 좋습니다.
  • NULL 값 처리: NULL 값을 저장할 필요가 있다면, 반드시 Nullable 데이터 타입을 명시적으로 사용하세요.
  • 쿼리 매개변수화: 반복되거나 복잡한 쿼리는 매개변수화하여 코드 재사용성을 높이고 유지보수를 용이하게 합니다.
  • 타입 안정성: 리터럴을 사용할 때 필요에 따라 CAST 연산 등을 통해 명시적인 데이터 타입 지정을 고려하여 타입 관련 오류를 방지하세요.

태그: ClickHouse SQL Database Data Analytics Query Language

7월 27일 23:40에 게시됨