메인 콘텐츠로 건너뛰기
Join Order Benchmark (JOB)는 실제 데이터셋(IMDb의 스냅샷)을 기반으로 한, 상관관계가 높은 데이터에 대해 113개의 분석 쿼리로 쿼리 최적화기를 검증하는 벤치마크입니다. 도입 이후 JOB 벤치마크는 카디널리티 추정과 조인 순서 최적화를 포함해 관계형 데이터베이스 쿼리 최적화기의 성능을 평가하는 사실상의 표준이 되었습니다. 균등하고 서로 독립적인 데이터를 가정하는 합성 벤치마크와 달리, JOB는 편향과 상관관계가 있는 실제 데이터를 사용하므로 조인 순서 최적화와 카디널리티 추정에 까다로운 테스트입니다. 이 데이터셋은 21개 테이블에 걸쳐 약 7,400만 개의 행을 포함하며, ClickHouse에서 압축 시 약 1.15 GiB를 차지합니다. 113개의 쿼리는 33개의 패밀리(133)로 구성됩니다. 같은 패밀리 내의 쿼리(a, b, c, …)는 동일한 조인 그래프를 공유하지만 선택 프레디케이트는 서로 다릅니다. 참고

테이블 생성

JOB 데이터셋은 21개의 테이블로 구성된 IMDb의 스냅샷입니다. 테이블 정의는 ClickHouse 리포지토리의 init_cloud.sql에서 확인할 수 있습니다. 각 테이블은 프라이머리 키 컬럼 id를 기준으로 정렬된 MergeTree 엔진을 사용하며, 이는 모든 테이블이 id integer NOT NULL PRIMARY KEY를 선언하는 원본 PostgreSQL 스키마를 반영한 것입니다. 널 허용 PostgreSQL 컬럼은 Nullable(...) 타입에 매핑됩니다. 테이블을 생성하세요:
curl -O https://raw.githubusercontent.com/ClickHouse/ClickHouse/master/tests/benchmarks/job/init_cloud.sql
clickhouse client --query "CREATE DATABASE IF NOT EXISTS job"
clickhouse client --database job --queries-file init_cloud.sql

데이터 로드

데이터는 JOB에서 사용된 원본 IMDb 스냅샷에서 가져오며, 각 테이블별 CSV file 하나(aka_name.csv, title.csv, …)로 배포됩니다. 이 CSV들은 ESCAPE '\'를 사용하는 PostgreSQL COPY 의미 체계를 따릅니다. 즉, 백슬래시는 따옴표로 묶인 field 안에서만 따옴표 문자를 이스케이프하고, 따옴표 밖에서는 문자 그대로 취급됩니다. ClickHouse는 RFC 4180 CSV(따옴표 이중화, 백슬래시 이스케이프 없음)를 기대하므로, 먼저 파일을 다시 인코딩해야 합니다. convert_csv.py는 이 재인코딩을 수행합니다. 이 스크립트는 원본 CSV를 stdin에서 읽고 표준 CSV를 stdout에 기록하며, 내부 따옴표는 이중화하고 따옴표로 묶이지 않은 빈 field는 그대로 유지합니다(ClickHouse는 이를 Nullable 컬럼의 NULL로 매핑합니다). 원본 CSV로 테이블을 빌드하려면:
  • 테이블을 생성하십시오(위 참고).
  • Join Order Benchmark 리포지토리의 지침에 따라 IMDb 데이터 집합을 imdb.tgz file로 다운로드하십시오.
  • 데이터를 변환하고 가져오십시오:
set -euo pipefail

for table in aka_name aka_title cast_info char_name comp_cast_type company_name \
             company_type complete_cast info_type keyword kind_type link_type \
             movie_companies movie_info movie_info_idx movie_keyword movie_link \
             name person_info role_type title; do
    echo "Loading ${table} ..."
    python3 convert_csv.py < "${table}.csv" > "${table}.clean.csv"
    clickhouse client --database job --query "INSERT INTO ${table} FORMAT CSV" < "${table}.clean.csv"
done
테이블(table)에 데이터가 채워지면, 나중에 더 빠르게 다시 가져올 수 있도록 Parquet로 내보낼 수 있습니다. 예: clickhouse client --database job --query "SELECT * FROM title ORDER BY id FORMAT Parquet" > title.parquet. 상세 테이블 크기:
Table크기(행 수)크기(ClickHouse에서 압축됨)
aka_name901,34331.86 MiB
aka_title361,47214.32 MiB
cast_info36,244,344296.25 MiB
char_name3,140,339107.95 MiB
comp_cast_type4132.00 B
company_name234,9978.38 MiB
company_type4162.00 B
complete_cast135,086748.80 KiB
info_type1131.25 KiB
keyword134,1701.88 MiB
kind_type7177.00 B
link_type18284.00 B
movie_companies2,609,12921.20 MiB
movie_info14,835,720300.46 MiB
movie_info_idx1,380,0358.01 MiB
movie_keyword4,523,93021.06 MiB
movie_link29,997178.21 KiB
name4,167,491131.16 MiB
person_info2,963,664154.12 MiB
role_type12246.00 B
title2,528,31278.04 MiB
합계74,190,1871.15 GiB
(ClickHouse의 압축된 크기는 system.tables.total_bytes에서 가져온 값이며, 위 테이블 정의를 기준으로 합니다.)

쿼리

113개의 JOB 쿼리는 ClickHouse 리포지토리의 여기에서 확인할 수 있습니다. 실행에 사용된 설정은 settings.json에 있습니다. 알려진 문제와 특정 쿼리에 관한 참고 사항은 README를 참조하십시오. 쿼리는 테이블 이름을 직접 참조하므로 job 데이터베이스에서 실행하십시오(예: clickhouse client --database job). 예시 쿼리(1a):
SELECT MIN(mc.note) AS production_note,
       MIN(t.title) AS movie_title,
       MIN(t.production_year) AS movie_year
FROM company_type AS ct,
     info_type AS it,
     movie_companies AS mc,
     movie_info_idx AS mi_idx,
     title AS t
WHERE ct.kind = 'production companies'
  AND it.info = 'top 250 rank'
  AND mc.note NOT LIKE '%(as Metro-Goldwyn-Mayer Pictures)%'
  AND (mc.note LIKE '%(co-production)%'
       OR mc.note LIKE '%(presents)%')
  AND ct.id = mc.company_type_id
  AND t.id = mc.movie_id
  AND t.id = mi_idx.movie_id
  AND mc.movie_id = mi_idx.movie_id
  AND it.id = mi_idx.info_type_id;
마지막 수정일 2026년 6월 29일