ClickHouse 사용 및 테이블 설계 입문
GitLab v19.2소개 페이지는 ClickHouse에 대한 개요를 파악하기에 매우 유용합니다. ClickHouse는 PostgreSQL과 같은 전통적인 OLTP(온라인 트랜잭션 처리) 데이터베이스와 많은 차이점이 있습니다. 이 점은 테이블을 설계할 때 중요하게 고려해야 합니다.
PostgreSQL과의 차이점#
소개 페이지는 ClickHouse에 대한 개요를 파악하기에 매우 유용합니다.
ClickHouse는 PostgreSQL과 같은 전통적인 OLTP(온라인 트랜잭션 처리) 데이터베이스와 많은 차이점이 있습니다. 기반 아키텍처가 다소 다르며, 처리 방식이 전통적인 데이터베이스보다 훨씬 더 CPU 집약적입니다. ClickHouse는 불변성(immutability)이 핵심 구성 요소인 로그 중심 데이터베이스입니다. 이러한 접근 방식의 장점은 잘 문서화되어 있습니다. 자세한 내용은 불변 데이터 저장소의 부상을 참조하세요. 그러나 이로 인해 업데이트가 훨씬 어려워집니다. UPDATE/DELETE 지원을 제공하는 작업에 대해서는 ClickHouse 문서를 참조하세요. 이러한 작업은 자주 실행되지 않아야 한다는 점이 주목할 만합니다.
이 점은 테이블을 설계할 때 중요하게 고려해야 합니다. 다음 두 가지 경우 중 하나입니다:
-
업데이트가 필요하지 않음 (최선의 경우)
-
업데이트가 필요한 경우, 쿼리 실행 중에 실행해서는 안 됨
ACID 호환성#
ClickHouse는 트랜잭션 지원에 대해 다소 다른 관점을 가지고 있으며, 특정 테이블에 삽입된 데이터 블록까지만 보장이 적용됩니다. 자세한 내용은 트랜잭션(ACID) 지원 문서를 참조하세요.
여러 테이블에 걸친 트랜잭션 지원은 구체화된 뷰(materialized views)에서만 지원되므로, 단일 쓰기 작업에서 여러 삽입을 수행하는 것은 피해야 합니다.
ClickHouse는 분석 쿼리를 위한 최고 수준의 지원을 제공하는 데 특화되어 있습니다. 집계(aggregation)와 같은 연산은 매우 빠르며, 이러한 기능을 강화하는 여러 가지 특징이 있습니다. ClickHouse에는 집계의 세부 사항을 다루는 유용한 블로그 게시물이 있습니다.
기본 인덱스, 정렬 인덱스 및 딕셔너리#
ClickHouse에서 인덱스를 이해하려면 “ClickHouse 기본 인덱스의 실용적인 소개”를 읽어보는 것이 강력히 권장됩니다.
특히 ClickHouse의 데이터베이스 인덱스 설계가 PostgreSQL과 같은 트랜잭션 데이터베이스의 인덱스와 어떻게 다른지에 주목하세요.
기본 인덱스 설계는 쿼리 성능에 매우 중요한 역할을 하므로 신중하게 설정해야 합니다. 전체 데이터 스캔은 더 오래 걸리기 때문에, 거의 모든 쿼리가 기본 인덱스에 의존해야 합니다.
MergeTree 테이블 엔진(ClickHouse의 기본 테이블 엔진)에서 인덱스가 쿼리 성능에 미치는 영향을 알아보려면 쿼리의 기본 키 및 인덱스 문서를 읽어보세요.
ClickHouse의 보조 인덱스는 다른 시스템에서 제공되는 것과 다릅니다. 데이터 블록을 건너뛰는 데 사용되므로 데이터 스킵 인덱스(data-skipping indexes)라고도 불립니다. 데이터 스킵 인덱스 문서를 참조하세요.
ClickHouse는 외부 인덱스로 사용할 수 있는 “딕셔너리(Dictionaries)”도 제공합니다. 딕셔너리는 메모리에서 로드되며 쿼리 런타임에 값을 조회하는 데 사용할 수 있습니다.
데이터 타입 및 파티셔닝#
ClickHouse는 SQL 호환 데이터 타입과 다음과 같은 몇 가지 특수 데이터 타입을 제공합니다:
-
Nested — 칼럼 내에 테이블을 시뮬레이션하므로 흥미롭습니다.
테이블을 설계할 때 가장 먼저 고려해야 할 핵심 설계 요소는 파티셔닝 키입니다. 파티션은 임의의 표현식일 수 있지만, 일반적으로 월, 일 또는 주와 같은 시간 단위를 사용합니다. ClickHouse는 가장 적은 수의 파티션 집합을 사용하여 읽는 데이터를 최소화하는 최선의 방식을 취합니다.
추천 읽기 자료:
샤딩 및 복제#
샤딩은 처리량을 늘리고 지연 시간을 줄이기 위해 데이터를 여러 ClickHouse 노드에 분산시키는 기능입니다. 샤딩 기능은 로컬 테이블을 기반으로 하는 분산 엔진을 사용합니다. 분산 엔진은 데이터를 저장하지 않는 “가상” 테이블입니다. 데이터를 삽입하고 쿼리하기 위한 인터페이스로 사용됩니다.
ClickHouse 문서와 복제 및 샤딩 섹션을 참조하세요. ClickHouse는 합의를 유지하기 위해 Zookeeper 또는 ClickHouse Keeper라는 컴포넌트를 통한 자체 호환 API를 사용할 수 있습니다.
노드가 설정된 후에는 클라이언트에서 보이지 않게 되며, 쓰기 및 읽기 쿼리 모두 어느 노드에서나 실행할 수 있습니다.
대부분의 경우, 클러스터는 보통 고정된 수의 노드(약 샤드 수)로 시작합니다. 샤드 재조정은 운영 비용이 많이 들며 엄격한 테스트가 필요합니다.
복제는 MergeTree 테이블 엔진에서 지원됩니다. 복제를 정의하는 방법에 대한 자세한 내용은 문서의 복제 섹션을 참조하세요. ClickHouse는 쿼럼에 참여하는 노드를 추적하기 위해 분산 조정 컴포넌트(Zookeeper 또는 ClickHouse Keeper)에 의존합니다. 복제는 비동기적이며 다중 리더 방식입니다. 삽입은 어느 노드에서나 실행할 수 있으며, 약간의 지연 시간이 지나면 다른 노드에서도 나타납니다. 원하는 경우, 특정 노드에 고정(stickiness)하여 읽기 작업이 최신 쓰기 데이터를 반영하도록 할 수 있습니다.
구체화된 뷰#
ClickHouse의 대표적인 기능 중 하나는 구체화된 뷰(materialized views)입니다. 기능적으로는 ClickHouse의 삽입 트리거와 유사합니다.
작동 방식을 더 잘 이해하기 위해 공식 문서의 views 섹션을 읽어보는 것을 권장합니다.
문서를 인용하면:
ClickHouse의 구체화된 뷰는 삽입 트리거처럼 구현됩니다. 뷰 쿼리에 집계가 있는 경우, 새로 삽입된 데이터 배치에만 적용됩니다. 소스 테이블의 기존 데이터 변경사항 (업데이트, 삭제, 파티션 삭제 등)은 구체화된 뷰를 변경하지 않습니다.
보안 및 합리적인 기본 설정#
ClickHouse 인스턴스는 다음 보안 권장 사항을 따라야 합니다:
사용자#
파일: users.xml 및 config.xml.
| 주제 | 보안 요구 사항 | 이유 |
|---|---|---|
| user_name/password | 사용자 이름은 비워 두어서는 안 됩니다. 비밀번호는 password_sha256_hex를 사용해야 하며 비워 두어서는 안 됩니다. | plaintext 및 password_double_sha1_hex는 안전하지 않습니다. 사용자 이름이 지정되지 않으면 비밀번호 없이 default가 사용됩니다. |
| access_management | 서버 구성 파일 users.xml 및 config.xml을 사용하세요. SQL 기반 워크플로를 피하세요. | SQL 기반 워크플로는 적어도 한 명의 사용자가 access_management를 가지고 있음을 의미하며, 이는 구성 파일을 통해 피할 수 있습니다. 이러한 파일은 “동일한 접근 엔티티를 두 가지 구성 방법으로 동시에 관리할 수 없습니다”라는 점을 고려할 때, 감사 및 모니터링도 더 쉽습니다. |
| user_name/networks | <ip>, <host>, <host_regexp> 중 적어도 하나를 설정해야 합니다. 모든 네트워크에 대한 접근을 허용하기 위해 <ip>::/0</ip>를 사용하지 마세요. |
네트워크 제어. (신중한 신뢰 원칙) |
| user_name/profile | 여러 사용자에게 유사한 속성을 설정하고 (사용자 인터페이스에서) 제한을 설정하기 위해 프로파일을 사용하세요. | 최소 권한 원칙 및 제한. |
| user_name/quota | 가능하면 사용자에 대한 할당량을 설정하세요. | 일정 기간 동안 리소스 사용을 제한하거나 리소스 사용을 추적합니다. |
| user_name/databases | 데이터에 대한 접근을 제한하고, 전체 접근 권한이 있는 사용자를 피하세요. | 최소 권한 원칙. |
네트워크#
파일: config.xml
| 주제 | 보안 요구 사항 | 이유 |
|---|---|---|
| mysql_port | 꼭 필요한 경우가 아니면 MySQL 접근을 비활성화하세요: <!-- <mysql_port>9004</mysql_port> -->. |
불필요한 포트 및 기능 노출 차단. (심층 방어 원칙) |
| postgresql_port | 꼭 필요한 경우가 아니면 PostgreSQL 접근을 비활성화하세요: <!-- <mysql_port>9005</mysql_port> --> |
불필요한 포트 및 기능 노출 차단. (심층 방어 원칙) |
| http_port/https_port & tcp_port/tcp_port_secure | SSL-TLS를 구성하고 비SSL 포트를 비활성화하세요: <!-- <http_port>8123</http_port> --><!-- <tcp_port>9000</tcp_port> -->그리고 보안 포트를 활성화하세요: <https_port>8443</https_port><tcp_port_secure>9440</tcp_port_secure> |
전송 중 데이터 암호화. (심층 방어 원칙) |
| interserver_http_host | ClickHouse가 클러스터로 구성된 경우 interserver_https_host(<interserver_https_port>9010</interserver_https_port>)를 위해 interserver_http_host를 비활성화하세요. |
전송 중 데이터 암호화. (심층 방어 원칙) |
스토리지#
| 주제 | 보안 요구 사항 | 이유 |
|---|---|---|
| 권한 | ClickHouse는 기본적으로 clickhouse 사용자로 실행됩니다. root로 실행하는 것은 절대 필요하지 않습니다. 폴더에 최소 권한 원칙을 적용하세요: /etc/clickhouse-server, /var/lib/clickhouse, /var/log/clickhouse-server. 이 폴더들은 clickhouse 사용자와 그룹에 속해야 하며, 다른 시스템 사용자는 접근할 수 없어야 합니다. | 기본 비밀번호, 포트 및 규칙은 “열린 문”입니다. (안전하게 실패하고 보안 기본값 사용 원칙) |
| 암호화 | RED 데이터를 처리하는 경우 로그 및 데이터에 암호화된 스토리지를 사용하세요. 쿠버네티스에서는 사용되는 StorageClass가 암호화되어야 합니다. GKE와 EKS는 이미 모든 저장 데이터를 암호화합니다. 이 경우 자체 키를 사용하는 것이 좋지만 필수는 아닙니다. | 저장 데이터 암호화. (심층 방어) |
로깅#
| 주제 | 보안 요구 사항 | 이유 |
|---|---|---|
| logger | log 및 errorlog는 정의되어야 하며 clickhouse가 쓸 수 있어야 합니다. | 로그가 저장되도록 확인합니다. |
| SIEM | GitLab.com에 호스팅되는 경우, ClickHouse 인스턴스 또는 클러스터는 SIEM(내부 링크)에 로그를 보고해야 합니다. | GitLab은 중요한 정보 시스템 활동을 기록합니다. |
| 민감한 데이터 로깅 | 민감한 데이터가 기록될 수 있는 경우 쿼리 마스킹 규칙을 사용해야 합니다. 마스킹 규칙 예시를 참조하세요. | 칼럼 수준 암호화가 사용될 수 있으며 로그에서 민감한 데이터(키)가 노출될 수 있습니다. |
마스킹 규칙 예시#
<query_masking_rules>
<rule>
<name>hide SSN</name>
<regexp>(^|\D)\d{3}-\d{2}-\d{4}($|\D)</regexp>
<replace>000-00-0000</replace>
</rule>
<rule>
<name>hide encrypt/decrypt arguments</name>
<regexp>
((?:aes_)?(?:encrypt|decrypt)(?:_mysql)?)\s*\(\s*(?:'(?:\\'|.)+'|.*?)\s*\)
</regexp>
<replace>\1(???)</replace>
</rule>
</query_masking_rules>