實(shí)踐指南:基于 IMDB 數(shù)據(jù)集的查詢優(yōu)化器壓力測試)
ClickHouse Join Order BenchmarkJOB實(shí)踐指南基于 IMDB 數(shù)據(jù)集的查詢優(yōu)化器壓力測試【免費(fèi)下載鏈接】ClickHouseClickHouse? is a real-time analytics database management system項(xiàng)目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouseJoin Order BenchmarkJOB是數(shù)據(jù)庫查詢優(yōu)化器領(lǐng)域的經(jīng)典壓力測試基準(zhǔn)它由 113 條分析型查詢構(gòu)成全部運(yùn)行在一個(gè)真實(shí)世界、高度相關(guān)的數(shù)據(jù)集IMDB 電影數(shù)據(jù)庫快照之上。本文將以 ClickHouse 倉庫中的 tests/benchmarks/job/README.md 為核心結(jié)合倉庫內(nèi)的建表腳本、CSV 轉(zhuǎn)換工具、查詢樣例與CREATE TABLE源碼實(shí)現(xiàn)完整講解如何在 ClickHouse 中加載 JOB 數(shù)據(jù)、規(guī)避空結(jié)果與 NULL 兼容性問題并正確復(fù)現(xiàn)這一基準(zhǔn)。讀完本文你將掌握 JOB 在 ClickHouse 下的完整落地路徑與關(guān)鍵坑點(diǎn)。一、什么是 Join Order BenchmarkJOBJoin Order Benchmark 的核心目標(biāo)是用真實(shí)的高相關(guān)數(shù)據(jù)集“折磨”查詢優(yōu)化器它取自 Leis 等人在 VLDB 2015 發(fā)表的論文How Good Are Query Optimizers, Really?中提出的基準(zhǔn)全部查詢圍繞 IMDB 快照構(gòu)建表之間存在大量 join 關(guān)系與列相關(guān)性因此 join 順序的選擇會顯著影響執(zhí)行性能。ClickHouse 倉庫將其納入 tests/benchmarks 目錄與 TPC-H、TPC-DS 并列用于評估和驅(qū)動自身查詢優(yōu)化器的演進(jìn)。在 tests/benchmarks/README.md 中每個(gè)基準(zhǔn)子目錄都遵循統(tǒng)一的結(jié)構(gòu)約定文件 / 目錄說明init.sql建表語句CREATE TABLE 定義settings.json運(yùn)行查詢時(shí)應(yīng)使用的 ClickHouse 設(shè)置用于保持 SQL 標(biāo)準(zhǔn)兼容queries/查詢文件對應(yīng)到 JOB 子目錄即 tests/benchmarks/job/init.sql、tests/benchmarks/job/settings.json 與 tests/benchmarks/job/queries后者內(nèi)含 113 個(gè)查詢文件從1a.sql一直到33c.sql。JOB 查詢按主題分組命名例如1a.sql、2c.sql、32a.sql等每個(gè)查詢都帶有明確的篩選條件與多表 join 結(jié)構(gòu)是對優(yōu)化器代價(jià)模型、join 重排與執(zhí)行引擎的綜合檢驗(yàn)。二、加載數(shù)據(jù)schema 與 NULL 語義2.1 init.sql 是原始 schematests/benchmarks/job/init.sql 是 JOB 基準(zhǔn)的原始、未修改schema包含 21 張 IMDB 表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。文件中的列定義是 PostgreSQL 風(fēng)格CREATE TABLE cast_info ( id integer NOT NULL PRIMARY KEY, person_id integer NOT NULL, movie_id integer NOT NULL, person_role_id integer, note text, nr_order integer, role_id integer NOT NULL );關(guān)鍵點(diǎn)在于這些列除非顯式聲明NOT NULL否則都是可空nullable的。例如person_role_id、note、nr_order沒有NOT NULL約束意味著它們可能包含 NULL 值。2.2 為什么必須設(shè)置 data_type_default_nullable1ClickHouse 的默認(rèn)行為與 PostgreSQL 相反在沒有顯式說明時(shí)列默認(rèn)為非空。因此直接執(zhí)行init.sql會導(dǎo)致原本可空的列被建成非空列而 IMDB 數(shù)據(jù)行中包含真實(shí) NULL 值加載時(shí)就會失敗。解決辦法是傳入data_type_default_nullable1設(shè)置讓所有未顯式標(biāo)注NOT NULL的列自動建為Nullable類型。README 給出的建表命令為clickhouse client --data_type_default_nullable1 --queries-file init.sql該設(shè)置同樣固化在基準(zhǔn)自帶的 tests/benchmarks/job/settings.json 中作為運(yùn)行 JOB 查詢時(shí)推薦的統(tǒng)一配置{ settings: { data_type_default_nullable: 1 } }從源碼層面看這一設(shè)置由CREATE TABLE的執(zhí)行器直接消費(fèi)。在 src/Interpreters/InterpreterCreateQuery.cpp 中構(gòu)建列類型時(shí)會讀取該設(shè)置bool make_columns_nullable mode LoadingStrictnessLevel::SECONDARY_CREATE !already_normalized_on_initiator !is_restore_from_backup context_-getSettingsRef()[Setting::data_type_default_nullable];即當(dāng)data_type_default_nullable為真時(shí)CREATE TABLE解析出的每一列都會通過getColumnType(...)被包裝為 Nullable 類型除非列聲明中明確寫了NOT NULL。這解釋了為什么init.sql中那些未標(biāo)注NOT NULL的列能夠在 ClickHouse 中正確保存 NULL并與 IMDB 數(shù)據(jù)一致。注意源碼中的條件也提示了該設(shè)置的生效邊界它在加載/主創(chuàng)建路徑SECONDARY_CREATE之前的加載嚴(yán)格度級別生效且跳過已規(guī)范化與備份恢復(fù)等內(nèi)部場景。2.3 ClickHouse Cloud使用 init_cloud.sql在 ClickHouse Cloud 上README 建議改用 tests/benchmarks/job/init_cloud.sql 而非init.sql。該文件是同一 schema 的“顯式 ClickHouse 類型翻譯版”用于繞開 cloud 共享 catalog 中的一個(gè)已知問題上游 issue 編號為 bug-97287。與原始init.sql相比init_cloud.sql做了兩類關(guān)鍵翻譯類型映射PostgreSQL 類型顯式映射為 ClickHouse 類型——integer NOT NULL→Int32可空integer→Nullable(Int32)text/character varying→String可空列則Nullable(String)。存儲引擎與排序鍵每張表統(tǒng)一使用ENGINE MergeTree ORDER BY id把原始 schema 中的id integer NOT NULL PRIMARY KEY對應(yīng)為 ClickHouse 的排序鍵sorting keyORDER BY id這是 ClickHouse 主鍵語義稀疏索引、用于裁剪與 PostgreSQL 主鍵語義的自然對應(yīng)。例如cast_info在init_cloud.sql中表現(xiàn)為CREATE TABLE cast_info ( id Int32, person_id Int32, movie_id Int32, person_role_id Nullable(Int32), note Nullable(String), nr_order Nullable(Int32), role_id Int32) ENGINE MergeTree ORDER BY id;2.4 數(shù)據(jù)文件的預(yù)處理convert_csv.pyJOB 的 IMDB 數(shù)據(jù)集以 PostgreSQL COPY 導(dǎo)出的 CSV 形式提供。該格式與 ClickHouse 的 CSV 解析器存在一個(gè)微妙差異Postgres 的 CSV 只在帶引號的字段內(nèi)部把反斜杠當(dāng)作轉(zhuǎn)義字符例如5 9\解析為5 9在引號之外反斜杠是普通字面字符例如未加引號的值可能在分隔符前以\結(jié)尾。Python 標(biāo)準(zhǔn)庫csv模塊會在所有位置應(yīng)用escapechar會破壞后一種情況因此 ClickHouse 倉庫專門提供了 tests/benchmarks/job/convert_csv.py 作為預(yù)處理工具它用一個(gè)小型狀態(tài)機(jī)按 Postgres 語義逐字段解析并重新輸出為標(biāo)準(zhǔn)雙引號轉(zhuǎn)義doubled-quote的 RFC 4180 CSVClickHouse 才能正確解析。該腳本的工程細(xì)節(jié)非常值得借鑒空字段保留為空的處理未加引號的空字段被保留為空字符串ClickHouse 對Nullable列會自動映射為 NULL——這與init.sql/init_cloud.sql的可空列設(shè)計(jì)正好閉環(huán)。快速路徑優(yōu)化對于整行既不包含也不包含\的物理行它必然不含有未閉合引號或轉(zhuǎn)義屬于合法 CSV腳本會原樣透傳而不做任何解析顯著加速海量純文本行的處理??缧凶侄螤顟B(tài)解析器支持引號字段跨越多行記錄未完整時(shí)返回等待更多輸入并在輸入結(jié)束時(shí)檢測“未終止的引號字段或尾部轉(zhuǎn)義”向 stderr 報(bào)錯(cuò)并返回退出碼 1防止靜默截?cái)?。使用方式為?biāo)準(zhǔn)的管道式文本處理cat imdb.csv | python3 convert_csv.py imdb_rfc4180.csv之后即可用 ClickHouse 的INSERT ... FROM INFILE或clickhouse-client --query裝載轉(zhuǎn)換后的 CSV。三、運(yùn)行 JOB 查詢數(shù)據(jù)加載完成后即可逐個(gè)執(zhí)行 tests/benchmarks/job/queries 中的查詢文件。每個(gè)文件是一條完整的分析查詢例如1a.sql查詢多部影片的制片注記、片名與年份涉及company_type、info_type、movie_companies、movie_info_idx、title五表 join并帶有LIKE模糊匹配與多條件過濾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;而2c.sql則在company_name、keyword、movie_companies、movie_keyword、title五張表上通過等值連接與字符串過濾如cn.country_code [sm]、k.keyword character-name-in-title做聚合。可以看到JOB 查詢大量使用“星型鏈?zhǔn)健钡幕旌?join 模式表與表之間存在高度相關(guān)的選擇謂詞這正是對優(yōu)化器 join 順序枚舉能力與代價(jià)估計(jì)精度的嚴(yán)苛檢驗(yàn)。運(yùn)行單個(gè)查詢可使用 clickhouse-clientclickhouse client --data_type_default_nullable1 --queries-file queries/1a.sql結(jié)合 tests/benchmarks/job/settings.json 中的data_type_default_nullable1設(shè)置可以保證查詢環(huán)境與建表環(huán)境一致。若需要批量評估全部 113 個(gè)查詢可以將queries/目錄中的文件按需拼接例如cat queries/*.sql | clickhouse client --multiquery并配合 ClickHouse 的clickhouse-benchmark參見 programs/benchmark進(jìn)行時(shí)間與吞吐統(tǒng)計(jì)。四、已知問題清單Known ProblemsREADME 明確記錄了兩類已知問題在復(fù)現(xiàn)基準(zhǔn)時(shí)務(wù)必留意ClickHouse Cloud 必須使用init_cloud.sql由于 cloud 共享 catalog 存在已知缺陷上游 issue bug-97287在 Cloud 上直接執(zhí)行init.sql會失敗。init_cloud.sql將同一 schema 翻譯為顯式 ClickHouse 類型Int32/Nullable(...)/String統(tǒng)一MergeTree ORDER BY id以規(guī)避該問題詳見 tests/benchmarks/job/init_cloud.sql。自建部署不受影響可繼續(xù)使用原始init.sql并依賴data_type_default_nullable1。部分原始查詢返回空結(jié)果113 個(gè)查詢中有 5 個(gè)——2c、5a、5b、10b、32a——在 IMDB 數(shù)據(jù)快照上會返回空結(jié)果這是預(yù)期行為并非 ClickHouse 缺陷。原因在于 JOB 數(shù)據(jù)集與原始查詢之間存在數(shù)據(jù)不匹配問題可復(fù)現(xiàn)性問題詳見上游 gregrahn/join-order-benchmark 倉庫的 issue #11。因此在統(tǒng)計(jì)基準(zhǔn)結(jié)果時(shí)建議將這 5 條查詢單獨(dú)標(biāo)記或排除避免將其計(jì)入執(zhí)行計(jì)劃質(zhì)量評估例如2c.sql中的過濾條件k.keyword character-name-in-title與cn.country_code [sm]在當(dāng)前數(shù)據(jù)快照上沒有同時(shí)滿足的記錄因而結(jié)果為空。五、在 ClickHouse 中復(fù)現(xiàn) JOB 的完整流程小結(jié)準(zhǔn)備 IMDB/JOB 數(shù)據(jù)集文件來自 Join Order Benchmark 倉庫的 IMDB Data Set。用 tests/benchmarks/job/convert_csv.py 將 Postgres-COPY CSV 預(yù)處理為 RFC 4180 標(biāo)準(zhǔn) CSV。選擇建表腳本本地/自建 ClickHouse 用 tests/benchmarks/job/init.sql并配合--data_type_default_nullable1ClickHouse Cloud 直接用 tests/benchmarks/job/init_cloud.sql。導(dǎo)入數(shù)據(jù)確保可空列正確接收 NULL。逐個(gè)或批量執(zhí)行 tests/benchmarks/job/queries 中的 113 條查詢評估 join 順序與執(zhí)行計(jì)劃注意2c、5a、5b、10b、32a預(yù)期返回空結(jié)果。通過上述步驟你可以在 ClickHouse 上完整復(fù)現(xiàn)這一經(jīng)典的查詢優(yōu)化器壓力測試并借助 tests/benchmarks/README.md 中約定的init.sqlsettings.jsonqueries/結(jié)構(gòu)將其擴(kuò)展為項(xiàng)目內(nèi)統(tǒng)一的 SQL 基準(zhǔn)目錄。JOB 的全部核心資源——原始與云端兩種 schema、113 條查詢、預(yù)處理腳本與推薦設(shè)置——都已固化在 ClickHouse 倉庫的 tests/benchmarks/job 目錄下可直接對照使用?!久赓M(fèi)下載鏈接】ClickHouseClickHouse? is a real-time analytics database management system項(xiàng)目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考