ClickHouse는 고성능 컬럼형 데이터베이스 관리 시스템으로, SQL 표준을 준수하면서도 분석 작업에 최적화된 독자적인 확장 기능을 제공합니다. 이 문서는 ClickHouse의 SQL 구문 체계를 심도 있게 다루어, 개발자들이 더욱 효과적으로 쿼리 언어를 활용할 수 있도록 돕습니다.
-
구문 분석 메커니즘 ClickHouse는 쿼리 유형에 따라 두 가지 파서(Parser)를 사용하여 최적화된 처리를 수행합니다.
-
전체 SQL 파서:
INSERT쿼리의 데이터 부분(values)을 제외한 모든 SQL 쿼리를 처리하는 재귀 하향식 파서입니다. -
데이터 형식 파서:
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 파서를 사용하게 할 수 있습니다.
- 기본 구문 요소 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 `판매_기록`;
- 리터럴 상세
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$와 같은 식별자는 임의로 지정할 수 있습니다.
- 고급 기능 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 * 3은 plus(1, multiply(2, 3))와 같이 변환되어 계산됩니다.
- 표현식 및 별칭
표현식은 식별자, 리터럴, 함수 호출, 서브쿼리 등의 조합으로 구성됩니다.
AS키워드를 사용하여 표현식의 결과나 컬럼에 별칭(Alias)을 부여할 수 있습니다. 이는 쿼리의 가독성을 높이고 복잡한 표현식을 단순화하는 데 유용합니다.
SELECT
item_price * quantity_sold AS total_revenue,
toYYYYMMDD(transaction_time) AS transaction_day
FROM order_details;
- 권장 활용 방안
- 대량
INSERT성능: 대규모 데이터 삽입 시VALUES구문을 활용하면 효율성을 극대화할 수 있습니다. - 식별자 명명: 특별한 이유가 없다면 인용 부호 없는 일반 식별자를 사용하여 쿼리를 간결하게 유지하는 것이 좋습니다.
NULL값 처리:NULL값을 저장할 필요가 있다면, 반드시Nullable데이터 타입을 명시적으로 사용하세요.- 쿼리 매개변수화: 반복되거나 복잡한 쿼리는 매개변수화하여 코드 재사용성을 높이고 유지보수를 용이하게 합니다.
- 타입 안정성: 리터럴을 사용할 때 필요에 따라
CAST연산 등을 통해 명시적인 데이터 타입 지정을 고려하여 타입 관련 오류를 방지하세요.