第 18 章 · ClickHouse 生态全景互动图

三种形态对照 · UDF 类型选择 · BI / 流批生态地图

① 三种形态对照
② UDF 类型选择决策
③ BI / 流批生态地图

clickhouse-local vs chdb vs server · 适用场景对照

点击卡片查看每种形态的「适用 / 不适用」清单. ClickHouse 同一个核, 三种壳, 选错了就会做无用功.

clickhouse-local CLI

单进程二进制, 不开服务, 文件即表.

体积 ~300MB · 启动 <100ms · 状态 = 当前命令

chdb In-process

同一个核做成动态库, 直接在 Python/Go 里调用.

pip install chdb · 进程内零网络 · 可持久化

clickhouse-server Daemon

常驻服务, 多用户/多副本/集群, 全功能形态.

长连接 · 副本/分片 · ZK/Keeper

clickhouse-local · 适用 vs 不适用

✓ 推荐场景
    ✗ 不推荐
      典型一行命令
      
            

      三者对比矩阵

      维度 clickhouse-local chdb clickhouse-server
      启动方式命令行二进制动态库/Python 包systemd 守护进程
      进程数1 (短生命)0 (寄生在宿主)1 (常驻)
      网络协议TCP 9000 / HTTP 8123
      多用户/权限RBAC 完整
      副本/分片支持
      持久化每次新进程, 默认无session 模式有有 (主战场)
      典型用户SRE/数据工程师数据科学家OLAP 平台运维
      类比工具SQL 版 awkSQLite + DuckDBMySQL/PG 服务

      UDF 类型选择决策

      ClickHouse 提供两类 UDF: SQL UDFExecutable UDF. 前者本质是宏, 后者每行触发外部进程, 性能差异可达 100×. 回答下面 3 个问题, 看选哪种.

      Q1 · 函数体能不能写成一段纯 SQL 表达式?

      → 用 SQL UDF (CREATE FUNCTION)

      纯 SQL 表达式宏, 编译期内联, 几乎零开销.

      CREATE FUNCTION trim_url AS (u) -> replaceRegexpOne(u, '\\?.*$', '');
      SELECT trim_url('/p?x=1&y=2');  -- '/p'

      ✓ 性能与内置函数等同 ✓ 容易回滚 ✓ 集群可见

      ✗ 不能写循环/IO/状态

      → 用聚合函数组合 / 物化视图, 不是 UDF 范畴

      ClickHouse 的 UDF 不支持自定义聚合状态 (CK 24.x 之前). 跨行聚合应当用内置 arrayReduce / groupArray + 处理函数, 或写入物化视图增量计算.

      SELECT arrayReduce('sum', groupArray(value)) FROM t GROUP BY k;

      真要写自定义聚合, 通常应改造为 C++ 扩展函数, 不在 UDF 范围.

      → 用 Executable UDF (低频时可接受)

      外部脚本 (Python/Bash/Go), 通过 stdin/stdout 一行一调用. 配置在 /etc/clickhouse-server/*_function.xml.

      <function>
        <type>executable</type>
        <name>py_upper</name>
        <return_type>String</return_type>
        <argument><type>String</type></argument>
        <format>TabSeparated</format>
        <command>python3 /opt/udf/upper.py</command>
      </function>

      ✓ 灵活: 任何语言 / 调外部模型

      ✗ 启动外部进程开销大, 1k 行就能拖到秒级

      ! 必须严格限制权限: execute_direct 子目录, 用专用 OS 用户

      → 不要在 SQL 内做! 把数据导出处理

      大表全行扫 + 外部脚本 = 千万次 fork, 即使 execute_pool 也救不了. 正确做法:

      • 把热数据导出 Parquet, 用 Spark/Flink 批处理
      • 或用物化视图先做轻量预处理, 减少 UDF 调用基数
      • 或把模型用 ONNX/C++ 接到 chdb / server 内置函数库

      ✗ 反例: SELECT bert_score(text) FROM logs -- 千万行, 必崩

      BI / 流批生态地图

      ClickHouse 处在"分析层", 上游接数据源, 下游接 BI / 应用. 下面展示常见集成方向.

      flowchart LR classDef src fill:#1f2630,stroke:#5a64ea,color:#e6edf3 classDef stream fill:#1f2630,stroke:#ff8c42,color:#e6edf3 classDef ck fill:#fbff37,stroke:#fbff37,color:#0e1116,font-weight:bold classDef bi fill:#1f2630,stroke:#3fb950,color:#e6edf3 classDef tool fill:#1f2630,stroke:#8b949e,color:#e6edf3 subgraph SRC[数据源] MySQL[(MySQL)]:::src PG[(PostgreSQL)]:::src Kafka[(Kafka)]:::src S3[(S3 / OSS)]:::src Files[CSV / Parquet 文件]:::src end subgraph PIPE[采集与加工] CDC[Debezium / Flink CDC]:::stream Spark[Spark + clickhouse-spark]:::stream DBT[dbt-clickhouse]:::stream Airbyte[Airbyte]:::stream KafkaEng[Kafka 表引擎]:::stream end CK[ClickHouse 集群
      MergeTree + Replicated]:::ck subgraph CLIENT[客户端 / SDK] JDBC[JDBC / ODBC]:::tool Py[Python clickhouse-connect]:::tool Go[Go clickhouse-go]:::tool Node[Node.js @clickhouse/client]:::tool end subgraph BI[BI / 可视化] Superset[Apache Superset]:::bi Metabase[Metabase]:::bi Grafana[Grafana]:::bi Tableau[Tableau / PowerBI]:::bi end subgraph EMB[嵌入式形态] Local[clickhouse-local]:::tool chdb[chdb 库]:::tool end MySQL --> CDC PG --> CDC Kafka --> KafkaEng S3 --> Spark Files --> DBT CDC --> CK Spark --> CK Airbyte --> CK KafkaEng --> CK DBT --> CK CK --> JDBC CK --> Py CK --> Go CK --> Node JDBC --> Superset JDBC --> Metabase JDBC --> Tableau Py --> Grafana Files --> Local Files --> chdb
      数据源 采集/ETL ClickHouse 核 BI 工具 客户端/嵌入

      Grafana 官方 Dashboard 速查

      用途Dashboard ID说明
      ClickHouse 单实例总览14192查询 QPS / 内存 / 磁盘 / Mark Cache
      ClickHouse 集群副本13500副本延迟 / replication queue
      JVM-style overview2515老牌 Altinity 模板