发布时间:2026/7/24 23:15:05
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 到 Doris2.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 fARRAY{convert_type(inner)} # 基本类型映射 return TYPE_MAP.get(ck_type, VARCHAR(65533)) # 未知类型兜底为 VARCHAR2.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_namedb.ck_user_behavior, ck_columnsck_columns, ck_partition_byevent_date, ck_order_byck_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 ARRAYVARCHAR(65533), ext_info MAPVARCHAR(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_HOST127.0.0.1 DORIS_PORT8030 # Stream Load HTTP 端口 DORIS_USERroot DORIS_DBmigration_demo DORIS_TABLEuser_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, tolerance0.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常见问题QDDL 转换后查询变慢了A检查三点① Bucket 数是否根据数据量合理设置太小导致并发不足太大增加元数据压力② 分桶 Key 是否与查询模式匹配③ 需要 Join 的两张表是否配置了 Colocation Group。QStream Load 导入报错 too many open filesADoris BE 进程需要调整ulimit -n建议设为 65536 以上。Q补数期间 Doris 查询性能受影响A建议将补数任务放在业务低峰期执行或在导入时设置strict_mode false降低导入对查询的影响。

相关新闻

2026/7/24 23:15:05

AI应用开发四层技术栈:MCP协议与模块化实践

1. AI应用开发四层技术栈全景解读当我在2023年首次接触金融大模型问答机器人项目时,面对琳琅满目的技术方案曾一度陷入选择困难。直到梳理出MCP-Skills-Tool Calling-SubAgent这套分层架构,才真正打通了AI应用开发的任督二脉。这套架构就像建造摩天大楼的…

2026/7/24 23:10:04

【00002】

二、C语言2.1基本数据类型1.C语言开发步骤(1) vi编辑器1.使用vi打开软件vi filename.cvi编辑器三种模式: 底行模式(默认,其余模式可以ESC进入底行模式) 插入模式(底行模式输入i、a、o均可进入插…

2026/7/24 23:10:04

1A,30VIN,双灯,XZ4056V,反接保护

产品概述这是一款完整的单节锂离子电池采用涓流、恒流、恒压控制的线性充电器,充电电流范围100mA-1000mA之间可设置。芯片底部有散热片的ESOP8封装与较少的外部元件数目而成为便携式应用的理想选择。可以适合USB电源和适配器电源工作。该充电器有电池温度监控&#…

2026/7/25 0:40:46

小爱音箱变身AI管家:5分钟打造你的智能语音助手终极指南

小爱音箱变身AI管家:5分钟打造你的智能语音助手终极指南 【免费下载链接】mi-gpt 🏠 将小爱音箱接入 ChatGPT 和豆包,改造成你的专属语音助手。 项目地址: https://gitcode.com/GitHub_Trending/mi/mi-gpt 想让家里的小爱音箱不再只是…

2026/7/25 0:40:46

猫抓视频嗅探工具:你的网页视频下载专家指南

猫抓视频嗅探工具:你的网页视频下载专家指南 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 在数字内容无处不在的今天,我们…

2026/7/25 0:40:46

商家降本、骑手增收,诚心呈意为何是配送行业的破局答案?

跑同城配送的骑手,大多有过这样的感受:路上同行的人越来越多,手里的配送单价却一降再降,想多赚点就得熬更长的时间、跑更远的路;做餐饮的商家也有苦难言:线上订单看着红火,扣完平台抽成和配送费…

2026/7/25 0:40:46

Web 安全怎么学,OWASP Top 10 漏洞原理与 Burp Suite 实战详解

从原理到实战:Web 核心漏洞深度剖析 很多初学者在掌握了 Linux 基础和网络协议后,面对 Web 渗透测试往往感到无从下手。要么过度依赖自动化工具“一键扫描”,要么死记硬背 Payload 却不懂其背后的运行逻辑。真正的进阶之路,在于深…

2026/7/25 0:35:46

2026年商用清洁机器人品牌推荐榜:五大品牌全场景实力解析

商用清洁机器人正在从“买一台设备试试看”,进入按场景、面积和运营目标成套部署的新阶段。 国际机器人联合会(IFR)发布的《World Robotics 2025—Industrial Robots》显示,2024年全球工业机器人新安装量达到542076台&#xff0c…

2026/7/23 12:54:51

Unity与Python本地通信:基于Flask的跨语言数据交换实战

1. 项目概述:为什么我们需要一个本地通信服务器?在游戏开发、数字孪生、仿真训练等众多领域,Unity作为强大的实时3D内容创作平台,其核心逻辑通常由C#驱动。然而,当我们需要进行复杂的数据分析、机器学习推理、科学计算…

2026/7/25 0:00:15

C++ string类模拟实现:从深拷贝到内存管理的完整指南

1. 项目概述:为什么我们要“手撕”string类?在C的学习道路上,尤其是从C语言过渡到C的“初阶”阶段,string类绝对是一个绕不开的核心。标准库里的std::string用起来太方便了,、find、substr,几个操作符和函数…

2026/7/25 0:00:15

三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

1. 先搞清楚“三角洲寻宝鼠”到底是什么工具从名称来看,“三角洲寻宝鼠”更像是一个资源查找或文件检索类工具,而不是游戏或娱乐软件。这类工具的核心价值在于帮助用户快速定位特定资源,比如文档、图片、压缩包或特定格式的文件。如果你经常需…

2026/7/25 0:00:15

VHF 甚高频语音喊话系统(桥梁智能防撞场景)核心优势

一、直达船员,预警链路最短营运船舶强制标配 VHF 船载电台,属于驾驶室常态化值守设备;预警语音直接传递至驾驶人员,区别于岸上声光报警(船员经常听不到)、短信 / 小程序(船员极少主动查看&#…

2026/7/23 23:42:43

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…