news 2026/7/24 23:15:02

Apache Doris 实战教程:手把手实现 ClickHouse 表结构迁移与数据校验

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Apache Doris 实战教程:手把手实现 ClickHouse 表结构迁移与数据校验

阅读前提

本教程假设你已具备:

  • 基本的 ClickHouse 使用经验(了解 MergeTree、分布式表概念)
  • 已部署 Apache Doris 集群(单节点或集群均可)
  • 会使用基本的 SQL 和 Shell 命令

第一步:环境准备 & 连接 Doris

首先确认 Doris 集群可连接,并创建目标 Database:

-- 连接 Doris(默认 MySQL 协议,端口 9030) -- mysql -h 127.0.0.1 -P 9030 -u root -- 创建目标数据库 CREATE DATABASE IF NOT EXISTS migration_demo; -- 查看集群状态 SHOW BACKENDS; SHOW FRONTENDS;

第二步:DDL 自动转换——从 CK 到 Doris

2.1 核心映射规则

ClickHouse 和 Apache Doris 在数据类型、表引擎、分区策略上存在差异,需要做以下映射:

# ck_to_doris_ddl.py —— DDL 类型映射核心代码 # ClickHouse → Doris 类型的映射表(覆盖快手支持的 22 种) TYPE_MAP = { "UInt8": "TINYINT", "UInt16": "SMALLINT", "UInt32": "INT", "UInt64": "BIGINT", "Int8": "TINYINT", "Int16": "SMALLINT", "Int32": "INT", "Int64": "BIGINT", "Float32": "FLOAT", "Float64": "DOUBLE", "String": "VARCHAR(65533)", "FixedString": "CHAR", "Date": "DATE", "DateTime": "DATETIME", "DateTime64": "DATETIME", "Array": "ARRAY", "Map": "MAP", "LowCardinality": "VARCHAR", # LowCardinality 展开为 VARCHAR "Enum8": "TINYINT", # Enum 通常转为基础类型 "Enum16": "SMALLINT", } def convert_type(ck_type): """转换 ClickHouse 类型到 Doris 类型""" # 处理 Nullable(Type) if ck_type.startswith("Nullable("): inner = ck_type[9:-1] return convert_type(inner) # Doris 默认支持 NULL,去除 Nullable 包装 # 处理 Array(Type) if ck_type.startswith("Array("): inner = ck_type[6:-1] return f"ARRAY<{convert_type(inner)}>" # 基本类型映射 return TYPE_MAP.get(ck_type, "VARCHAR(65533)") # 未知类型兜底为 VARCHAR

2.2 生成完整的 Doris DDL

# 接上文件 ck_to_doris_ddl.py import re def generate_doris_ddl(ck_table_name, ck_columns, ck_partition_by, ck_order_by): """ 根据 ClickHouse 表信息生成 Doris DDL 参数: ck_table_name: ClickHouse 表名 ck_columns: [(col_name, col_type), ...] ck_partition_by: ClickHouse 分区表达式 ck_order_by: ClickHouse 排序键列名列表 """ doris_table = ck_table_name.replace(".", "_") # 1. 生成列定义 col_defs = [] for col_name, col_type in ck_columns: doris_type = convert_type(col_type) col_defs.append(f" {col_name} {doris_type}") # 2. 从 ORDER BY 推导 DUPLICATE KEY(前两列作为 Key) key_cols = ck_order_by[:2] if len(ck_order_by) >= 2 else ck_order_by # 3. 分区策略:取第一个 Date/DateTime 列做 RANGE 分区 partition_col = ck_partition_by if ck_partition_by else "event_date" # 4. 分桶:按第一列 HASH,默认 32 桶 bucket_col = ck_order_by[0] if ck_order_by else ck_columns[0][0] bucket_num = 32 # 可根据分区数据量调整 ddl = f""" CREATE TABLE IF NOT EXISTS {doris_table} ( {','.join(col_defs)} ) ENGINE = OLAP DUPLICATE KEY({','.join(key_cols)}) PARTITION BY RANGE({partition_col}) () DISTRIBUTED BY HASH({bucket_col}) BUCKETS {bucket_num} PROPERTIES ( "replication_num" = "3" ); """ return ddl.strip() # ---------- 使用示例 ---------- if __name__ == "__main__": # 模拟一个 ClickHouse 表结构 ck_columns = [ ("event_date", "Date"), ("user_id", "UInt64"), ("event_type", "String"), ("event_value", "Float64"), ("event_time", "DateTime"), ("tags", "Array(String)"), ("ext_info", "Map(String, String)"), ] ck_order_by = ["user_id", "event_time"] ddl = generate_doris_ddl( ck_table_name="db.ck_user_behavior", ck_columns=ck_columns, ck_partition_by="event_date", ck_order_by=ck_order_by ) print("-- 生成的 Doris DDL --") print(ddl)

执行结果将生成类似以下 DDL:

-- 生成的 Doris DDL -- CREATE TABLE IF NOT EXISTS db_ck_user_behavior ( event_date DATE, user_id BIGINT, event_type VARCHAR(65533), event_value DOUBLE, event_time DATETIME, tags ARRAY<VARCHAR(65533)>, ext_info MAP<VARCHAR(65533),VARCHAR(65533)> ) ENGINE = OLAP DUPLICATE KEY(user_id, event_time) PARTITION BY RANGE(event_date) () DISTRIBUTED BY HASH(user_id) BUCKETS 32 PROPERTIES ( "replication_num" = "3" );

第三步:配置双跑——数据同时写入 CK 和 Doris

迁移期间,新增数据需要同时写入 ClickHouse 和 Apache Doris:

#!/bin/bash # dual_write.sh —— 离线数据双写脚本 DORIS_HOST="127.0.0.1" DORIS_PORT="8030" # Stream Load HTTP 端口 DORIS_USER="root" DORIS_DB="migration_demo" DORIS_TABLE="user_behavior" # 假设已有 Hive → CK 的导出文件 data_export.csv DATA_FILE="/data/export/data_export.csv" # Stream Load 写入 Doris curl --location-trusted -u ${DORIS_USER}: \ -H "label:dual_write_$(date +%s)" \ -H "column_separator:," \ -H "format:csv" \ -T ${DATA_FILE} \ http://${DORIS_HOST}:${DORIS_PORT}/api/${DORIS_DB}/${DORIS_TABLE}/_stream_load echo "Dual write completed: $(date)"

第四步:存量数据迁移——Hive 到 Doris

对于上游 Hive 数据完整的情况,直接复用已有 ETL 链路:

-- 通过 Doris Multi-Catalog 直接查询 Hive 并 INSERT INTO 目标表 -- 适用于 Hive 数据保留周期够长的场景 -- 1. 创建 Hive Catalog CREATE CATALOG hive_catalog PROPERTIES ( "type" = "hms", "hive.metastore.uris" = "thrift://hive-metastore:9083" ); -- 2. 将 Hive 数据批量写入 Doris 内表 INSERT INTO migration_demo.user_behavior SELECT event_date, user_id, event_type, event_value, event_time FROM hive_catalog.ods.user_behavior_hive WHERE event_date >= '2025-01-01'; -- 3. 查看导入状态 SHOW LOAD FROM migration_demo;

第五步:数据校验——确保迁移结果可靠

5.1 基础数据量校验

-- 第一层校验:行数和基础统计 -- 在 Doris 中执行 SELECT 'Doris' AS source, COUNT(*) AS row_count, SUM(event_value) AS total_value, COUNT(DISTINCT user_id) AS unique_users FROM migration_demo.user_behavior UNION ALL -- 对比 ClickHouse(需单独查询后贴入) -- 预期结果:row_count 和 total_value 应一致 SELECT 'ClickHouse' AS source, 1000000, 12345678.90, 50000;

5.2 维度聚合校验

-- 第二层:按核心维度 GROUP BY 对比 SELECT event_date, event_type, COUNT(*) AS cnt, SUM(event_value) AS sum_val, AVG(event_value) AS avg_val FROM migration_demo.user_behavior WHERE event_date >= '2025-06-01' GROUP BY event_date, event_type ORDER BY event_date, event_type LIMIT 100; -- 将此结果与 ClickHouse 中相同查询结果逐行对比

5.3 Float 精度校验

# float_check.py —— 精度容忍校验 import math def check_float_precision(ck_value, doris_value, tolerance=0.001): """ 检查 Float 类型精度偏差 参数: ck_value: ClickHouse 侧数值 doris_value: Doris 侧数值 tolerance: 相对容忍阈值(默认 0.1%) """ if ck_value == 0 and doris_value == 0: return True relative_error = abs(ck_value - doris_value) / max(abs(ck_value), abs(doris_value)) if relative_error > tolerance: print(f"⚠ 精度超标: CK={ck_value}, Doris={doris_value}, error={relative_error:.6f}") return False return True # 使用示例 assert check_float_precision(3.14159265, 3.14159) # True(偏差约 0.00008%) assert not check_float_precision(3.14, 3.25) # False(偏差约 3.5%,超标)

第六步:灰度切换

#!/bin/bash # gray_switch.sh —— 通过 OneSQL 或其他路由层逐步切换 # 1. 10% 流量打向 Doris echo "Gray release: 10% traffic" # onesql-cli set-route --table user_behavior --target doris --weight 10 # 2. 观察 24 小时,确认无异常 # 3. 50% 流量 echo "Gray release: 50% traffic" # onesql-cli set-route --table user_behavior --target doris --weight 50 # 4. 观察 24 小时 # 5. 100% 流量 echo "Full switch to Doris" # onesql-cli set-route --table user_behavior --target doris --weight 100

常见问题

Q:DDL 转换后查询变慢了?A:检查三点:① Bucket 数是否根据数据量合理设置(太小导致并发不足,太大增加元数据压力);② 分桶 Key 是否与查询模式匹配;③ 需要 Join 的两张表是否配置了 Colocation Group。

Q:Stream Load 导入报错 "too many open files"?A:Doris BE 进程需要调整ulimit -n,建议设为 65536 以上。

Q:补数期间 Doris 查询性能受影响?A:建议将补数任务放在业务低峰期执行,或在导入时设置"strict_mode" = "false"降低导入对查询的影响。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/24 23:14:59

Linear Loops功能详解:简化循环工程操作与自动化工作流

Linear 最近发布了 Loops 功能&#xff0c;这是一个专门为简化循环工程操作而设计的新工具。如果你经常需要处理重复性任务、批量操作或者需要自动化的工作流程&#xff0c;Loops 可能会成为你的新利器。这次我们重点看看它的核心功能、使用门槛、实际效果以及如何快速上手。Lo…

作者头像 李华
网站建设 2026/7/24 23:11:22

Claude Code v2.1.216性能优化:解决长会话卡顿与Agent行为异常

如果你正在使用 Claude Code 进行 AI 辅助编程&#xff0c;最近是否遇到过这样的困扰&#xff1a;代码编写到一半&#xff0c;编辑器响应越来越慢&#xff0c;甚至出现卡顿&#xff1f;或者你的 Agent 在执行复杂任务时行为异常&#xff0c;无法按预期完成工作&#xff1f;这正…

作者头像 李华
网站建设 2026/7/24 23:09:10

QKeyMapper:Windows游戏手柄键盘鼠标全能映射的终极解决方案

QKeyMapper&#xff1a;Windows游戏手柄键盘鼠标全能映射的终极解决方案 【免费下载链接】QKeyMapper [按键映射工具] QKeyMapper&#xff0c;Qt开发Win10&Win11可用&#xff0c;不修改注册表、不需重新启动系统&#xff0c;可立即生效和停止。支持游戏手柄映射到键鼠&…

作者头像 李华
网站建设 2026/7/24 23:03:44

大模型时代NLP技术演进与实战指南

1. 大模型时代下的NLP技术演进赵宇教授的新书《自然语言处理&#xff1a;大模型理论与实践》来得正是时候。作为一名长期关注NLP领域发展的从业者&#xff0c;我亲眼见证了从传统规则系统到统计方法&#xff0c;再到如今大模型主导的技术变迁。这本书的出版&#xff0c;恰好为想…

作者头像 李华
网站建设 2026/7/24 23:03:12

程序员转型大模型:核心技能与实战路线图

1. 程序员转型大模型的必要性2026年的技术格局已经清晰表明&#xff1a;不会使用大模型的程序员将面临严峻的职业危机。过去两年&#xff0c;我面试过上百名候选人&#xff0c;发现一个残酷的事实——传统编程能力正在快速贬值。那些只会写CRUD代码的程序员&#xff0c;薪资涨幅…

作者头像 李华
网站建设 2026/7/24 23:01:01

Centos7 编译安装Cmake+ffmpeg

1、系统准备安装好Centos7.9&#xff0c;并打好系统补丁&#xff0c;安装一些常用工具&#xff0c;关闭防火墙&#xff0c;yum -y update yum -y install git yum -y install vim yum -y install unzip yum -y install net-tools yum -y install wget yum -y install openssl-d…

作者头像 李华