Clickhouse 迁移到 Doris 的最佳实践

news2025/5/13 18:30:24

在这里插入图片描述

一、引言

在将数据从 Clickhouse 迁移到 Apache Doris / SelectDB Cloud 的过程中,涉及表结构迁移、查询语句迁移以及数据迁移等多个关键环节。每个环节都有其复杂性和需要注意的细节,本文将详细介绍这些内容及对应的最佳实践方法。

二、表结构迁移

(二)表结构创建要点

了解表引擎与数据模型对应关系

对于普通表引擎迁移且不包含特殊数据类型(如枚举、嵌套数据类型)时,需要清楚 Clickhouse 不同的表引擎与 Doris 的数据模型的对应关系。例如,Clickhouse 的 MergeTree 表引擎,在 Doris 中可根据业务场景选择合适的数据模型,如用于原始日志、操作记录等分析场景时,可对应 Doris 的 Duplicate 模型。

合理设置分桶相关参数

分桶数:不要使用 auto 分桶,应根据表的数据量通过计算公式得出合理的分桶数。例如,可以先预估表的未来数据增长规模,结合 Doris 集群的节点数量和性能,通过一定的测试和计算来确定分桶数,以确保数据在集群中能够均匀分布,提升查询性能。

分桶字段:充分考虑业务场景,选择经常在查询条件中出现的字段作为分桶字段,这样可以在查询时快速定位到相关数据,避免后期对表结构进行二次优化(分桶确定后,后期不可更改。除非是新建分区的分桶)。

处理特殊数据类型

Clickhouse 中有许多 Doris 不具备的数据类型,如无符号整型数据类型、嵌套数据类型等。在替换时,优先选择 Doris 中数据类型范围比 Clickhouse 原始字段范围更大的数据类型。例如,Clickhouse 中的 UInt32 类型,在 Doris 中可转换为 bigint 类型。

如果实在没有与之对应的 Doris 数据类型,可以考虑使用 Doris 的 text 数据类型,但这可能会对查询性能产生一定影响,需要谨慎使用。

(三)获取 CK 表结构

可以通过脚本一次性批量获取 Clickhouse 的表结构,核心 SQL 如下:

select create_table_query from system.tables where database = 'default' or database='tpch';

或者直接通过脚本的方式通过 client 遍历执行show create table xxx来获取 Clickhouse 的表结构。

三、查询语句迁移

(一)工具辅助

查询语句迁移目前有sql-glot工具提供帮助,将 Clickhouse 的查询语句从 Clickhouse 的日志中全部获取出来后,将SQL过一遍sql-glot,就能自动转换为Doris的查询语句,sql - glot 使用网站。 但可能存在一些不兼容的问题,导致转换失败。故还需要人为手动参与进去做一些修改:

(二)人工参与

梳理函数列表

梳理 Clickhouse 使用了哪些查询函数。

梳理 Doris 这边与之对应的函数列表。对于有对应的 Doris 函数,直接进行替换;对于不存在相应函数的情况,及时联系Doris官方人员做支持。

四、数据迁移

(一)迁移方式选择准则

从已有的用户迁移实践来看,应尽可能选用 Doris 能提供的原生导入方式来进行数据导入。现阶段,从 Clickhouse 迁移到 Doris/Cloud 有多种方式,如:

  • 在 Clickhouse 上导出为文件,然后调用 stream load 或者 S3 load 的方式
  • Spark connector
  • datax

(二)各工具可能存在的问题

Datax:其 Clickhouse reader 支持的 Clickhouse 的数据类型比较少,很多数据类型不支持,使用时需要慎重考虑。

Spark connector 和 Flink connector:如果直接读取 CK,会存在一些特殊数据类型不支持的问题(如 BITMAP)。

(三)推荐迁移方式

优先考虑将 Clickhouse 的数据导出成文件(如 parquet)到 HDFS 或者对象存储,然后使用 S3 LOAD 等方式把数据导入 Doris。具体操作如下:

环境配置

搭建 Doris 集群,确保集群环境稳定且各项配置正确。

准备好 HDFS / 对象存储,确保存储环境可用且权限设置正确。

检查环境中是否安装有 python3,部分导出工具可能依赖 python3 环境。

在 Doris 建表

建表时需将字段与 Clickhouse 对应,表模型对应可参考 Apache Doris 与 Clickhouse 字段及表模型对应关系。

注意 ORC 文件迁移要求 Clickhouse 和 Doris 表字段大小写相同。例如,Clickhouse 表的 DDL 如下:

CREATE TABLE ssb.lineorder
(
   `LO_ORDERKEY` UInt32,
   `LO_LINENUMBER` UInt8,
   `LO_CUSTKEY` UInt32,
   `LO_PARTKEY` UInt32,
   `LO_SUPPKEY` UInt32,
   `LO_ORDERDATE` Date,
   `LO_ORDERPRIORITY` LowCardinality(String),
   `LO_SHIPPRIORITY` UInt8,
   `LO_QUANTITY` UInt8,
   `LO_EXTENDEDPRICE` UInt32,
   `LO_ORDTOTALPRICE` UInt32,
   `LO_DISCOUNT` UInt8,
   `LO_REVENUE` UInt32,
   `LO_SUPPLYCOST` UInt32,
   `LO_TAX` UInt8,
   `LO_COMMITDATE` Date,
   `LO_SHIPMODE` LowCardinality(String)
)
ENGINE = MergeTree
PARTITION BY toYear(LO_ORDERDATE)
ORDER BY (LO_ORDERDATE, LO_ORDERKEY)
SETTINGS index_granularity = 8192;

在 Doris 中的 DDL 如下:

CREATE TABLE `lineorder` (
 `LO_ORDERKEY` bigint NOT NULL COMMENT "",
 `LO_LINENUMBER` SMALLINT NOT NULL COMMENT "",
 `LO_CUSTKEY` bigint NOT NULL COMMENT "",
 `LO_PARTKEY` bigint NOT NULL COMMENT "",
 `LO_SUPPKEY` bigint NOT NULL COMMENT "",
 `LO_ORDERDATE` date NOT NULL COMMENT "",
 `LO_ORDERPRIORITY` varchar(16) NOT NULL COMMENT "",
 `LO_SHIPPRIORITY` SMALLINT NOT NULL COMMENT "",
 `LO_QUANTITY` SMALLINT NOT NULL COMMENT "",
 `LO_EXTENDEDPRICE` bigint NOT NULL COMMENT "",
 `LO_ORDTOTALPRICE` bigint NOT NULL COMMENT "",
 `LO_DISCOUNT` SMALLINT NOT NULL COMMENT "",
 `LO_REVENUE` bigint NOT NULL COMMENT "",
 `LO_SUPPLYCOST` bigint NOT NULL COMMENT "",
 `LO_TAX` SMALLINT NOT NULL COMMENT "",
 `LO_COMMITDATE` date NOT NULL COMMENT "",
 `LO_SHIPMODE` varchar(11) NOT NULL COMMENT ""
) ENGINE=OLAP
DUPLICATE KEY(`LO_ORDERKEY`)
PARTITION BY RANGE(`LO_ORDERDATE`)
(PARTITION p1 VALUES [('0000-01-01'), ('1993-01-01')),
PARTITION p2 VALUES [('1993-01-01'), ('1994-01-01')),
PARTITION p3 VALUES [('1994-01-01'), ('1995-01-01')),
PARTITION p4 VALUES [('1995-01-01'), ('1996-01-01')),
PARTITION p5 VALUES [('1996-01-01'), ('1997-01-01')),
PARTITION p6 VALUES [('1997-01-01'), ('1998-01-01')),
PARTITION p7 VALUES [('1998-01-01'), ('1999-01-01')))
DISTRIBUTED BY HASH(`LO_ORDERKEY`) BUCKETS 48
PROPERTIES (
"replication_allocation" = "tag.location.default: 3",
"in_memory" = "false",
"storage_format" = "V2"
);

配置导出工具

此方案为分布式导出方案,如果单表数据量小于两亿条,可直接采用 clickhouse - client 导出 orc 文件。直接导出语法参考如下:

clickhouse - client --password yourpassword  --query="select * from ssb.lineorder FORMAT ORC" > lineorder.ORC

分布式导出工具配置如下:

下载 ClickHouse 导出工具:

git clone   https://github.com/LOVEGISER/clickhouse_export.git

进入目录:

cd clickhouse_export/clickhouse_python_sink/

打开配置文件:

vim config.py

在配置文件中进行如下配置:

# -*- encoding=utf8 -*-

"""
-------------------------------------------------
@author: "xxxx"
@file: config.py
@time: xxxx
@desc: clickhouse_python_sink Server Config
-------------------------------------------------
"""
from log_utils import logger
#1. which table should want to been export
export_table_list = [
   {
     "db":"ssb", #指定数据库
     "table":"lineorder", #指定表
     "format":"ORC", #ORC/Parquet/CSVWithNames #指定导出格式
     "filenameExtension":"ORC", #ORC/Parquet/csv #指定导出文件后缀名
     "mode":"partition",#导出模式,可选按照partition分区导出或者all全量导出
     "partition_expr":"toYear(LO_ORDERDATE)",#指定的分区字段
     "upper_condition":"toYear(LO_ORDERDATE)<=999912",#结束分区
     "lower_condition":"toYear(LO_ORDERDATE)>=000001",#开始分区
     "partition_split_filed": "LO_TAX",#对数据量过大的partition按照split_filed再次切分
     "partition_split_filed_model": "continuous",#continuous:连续型(数据按照字段线性增长),discrete:离散型
     "partition_split_filed_type": "long" #datetime/long/date
   }
   # 可以同时指定多个表
  # ,{
  #    "db":"default",
  #    "table":"trips_np",
  #    "format": "Parquet",
  #    "mode":"all",
  #    "partition_expr":"",
  #    "upper_condition":"",
  #    "lower_condition":"",
  #    "partition_split_filed": "",
  #    "partition_split_filed_model": "",
  #    "partition_split_filed_type": ""
  #  }
]

#例子

'''
example:
export_table_list = [
   {
     "db":"default",
     "table":"trips",
     "mode":"all/partition",
     "partition_expr":"toYYYYMM(pickup_date)",
     "upper_condition":"toYYYYMM(pickup_date)<=201508",
     "lower_condition":"toYYYYMM(pickup_date)>=201506",
   }
]

'''
#example :./clickhouse-client --host=<host> --port=<port> --user=<user> --password=<password>;
clickhouse_connect_command = "clickhouse-client --host=*.*.*.* --port=9000"
#2.thread number use
process_number = 10
sub_partition_max_size=200000
#指定clickhouse的userfiles路径,导出的文件在此
user_files_path = "/mnt/data/clickhouse/user_files"

运行导出
执行以下命令运行导出:

python3 scheduler.py

工具会自动监测导出线程状态以及导出数据条数准确性。

  1. 数据上传 HDFS / 对象存储

上传对象存储:以 OSS 为例,先找到 ClickHouse 的 user_file 目录或者在 python 脚本中自定义的数据文件目录,然后用 ossutil64 上传整个目录到存储桶。例如:

./ossutil64 cp -r /mnt/data/clickhouse/user_files/ssb/lineorder oss://bucket/ssb/lineorder

腾讯 COS 和阿里 OSS 等对象存储的上传操作可参考对应官方文档,如

腾讯 COS:https://cloud.tencent.com/document/product/436/10976;

阿里 OSS:https://help.aliyun.com/document_detail/50451.html。

上传 HDFS:使用 HDFS 命令上传,例如:

hdfs dfs -put lineorder /lineorder

Doris Load 数据

S3 Load:针对 ClickHouse 导出的数据存到对象存储上,参考: s3 load

LOAD LABEL ssb.lineorder_oss
   (
       DATA INFILE("s3://bucket/filer/*")
       INTO TABLE lineorder
       FORMAT AS "orc"
   )
WITH S3
   (
       "AWS_ENDPOINT" = "*",
       "AWS_ACCESS_KEY" = "*",
       "AWS_SECRET_KEY"="*",
       "AWS_REGION" = "*"
   )
PROPERTIES
   (
       "timeout" = "3600" -- 如果数据量过大请合理配置超时时间
   );

数据验证

可以通过运行count(*)或者常用分析 SQL 对比 ClickHouse 验证结果,确保迁移的数据准确无误。

五、其他数据迁移方式补充

(一)ClickHouse->Apache Doris (Stream Load File)

此方案仅适用于数据量小的维度表(不建议超过 200M)且表数据不复杂的场景(需注意 csv 文件的分隔符与双引号问题),具体操作步骤如下:

环境配置:搭建好 Doris 环境,确保其正常运行。

在 Doris 建表:把字段与 ClickHouse 对应,保证表模型匹配,ORC 文件迁移要求 ClickHouse 和 Doris 表字段大小写相同。

导出数据

CSV 格式:运行clickhouse-client --password yourpassword --format_csv_delimiter="|" --query="select * from ssb.customer FORMAT CSV" > customer.csv导出数据。由于 ClickHouse 导出的 csv 文件中 string 和 date 等类型字段会带双引号,需使用sed -i 's/"//g' customer.csv命令处理。

JSON 格式:执行clickhouse-client --password yourpassword --query="select * from ssb.customer FORMAT JSON" > customer.json导出数据。因 clickhouse 导出的 json 文件带元数据信息,仅需 data 部分,可通过yum install -y jq安装 jq 工具,再执行cat customer.json | jq ".data" > customer_f.json处理。

Stream Load 导入 Doris

CSV 导入:执行curl --location-trusted -u root:****** -T customer.csv -H "column_separator:|" -H "label:customer_csv" http://host:port/api/ssb/customer/_stream_load,根据返回结果确认导入是否成功。

JSON 导入:Doris 默认支持最大导入 100MB 的 Json 文件,可修改相关参数增大限制。执行curl --location-trusted -u root:****** -H "format: json" -H "strip_outer_array: true" -T customer_f.json http://host:port/api/ssb/customer/_stream_load完成导入。

数据验证:通过运行count(*)或者常用分析 SQL 对比 ClickHouse 验证数据准确性。

(二)ClickHouse->Apache Doris (Spark-SQL)

Spark-SQL 迁移方案分为 http/grpc 两种,适用于不同的 ClickHouse 版本,ClickHouse 21.1.2.15 及以上版本使用 grpc 协议效率更高,具体流程如下:

环境准备:搭建 Doris;下载 Spark(版本需为 3.2 以上),并配置好相关环境变量,如SPARK_WORKER_CORESSPARK_WORKER_MEMORYSPARK_MASTER_HOSTSPARK_MASTER_PORTJAVA_HOME等。

在 Doris 建表:将字段与 ClickHouse 对应,构建合适的表结构。

Spark 配置

下载 ClicHouse 相关 jar 包(根据 http 或 grpc 版本选择),放入 spark/jars/ 目录。

下载 spark-doris-connector,放入 spark/jars/ 目录。

编辑$SPARK_HOME/conf/spark-defaults.conf,添加 ClickHouse 相关配置;编辑$SPARK_HOME/conf/``spark-env.sh,配置 Spark 集群相关参数。

配置 Clickhouse:若使用 grpc 协议做迁移,需在 ClickHouse 配置文件/etc/clickhouse-server/config.xml中打开 grpc 协议相关配置,并重启 ClickHouse 服务。

启动 Spark-SQL:先启动 Spark 集群(本次使用 standalone 模式),执行$SPARK_HOME/sbin/``start-all.sh;再启动 spark-sql,执行$SPARK_HOME/bin/spark-sql --executor-memory 24G --executor-cores 4,可通过执行select * from clickhouse.ssb.lineorder limit 10;测试连接。

Spark 中建 Doris 映射表:参考相关文档,执行CREATE TEMPORARY VIEW lineorder_sink USING doris OPTIONS("table.identifier"="ssb.lineorder","fenodes"="*.*.*.*:8030","user"="root","password"="*","sink.batch.size" = "100000");创建映射表。

迁移数据:根据 CK 数据分区情况,分批次迁移数据,如insert into lineorder_sink SELECT * FROM clickhouse.ssb.lineorder where LO_ORDERDATE >= '1998-01-01' and LO_ORDERDATE <= '1998-12-31';insert into lineorder_sink SELECT * FROM clickhouse.ssb.lineorder; ,注意若迁移失败,需先在 Doris 删除对应数据再重新导入。

数据验证:通过运行count(*)或者常用分析 SQL 对比 ClickHouse 验证结果。

六、迁移后优化与注意事项

(一)性能优化

索引优化:根据业务查询需求,在 Doris 中合理创建索引,如前缀索引、Bloom Filter 索引、Bitmap 倒排索引等,提高查询效率。例如,对于经常用于过滤条件的字段,可创建相应的索引。

物化视图:对于频繁查询的固定维度或聚合结果,创建物化视图。Doris 会自动维护物化视图的数据,查询时可直接从物化视图中读取数据,大幅提升查询性能。

数据分区与分桶调整:如果发现数据分布不均匀或查询性能未达预期,可根据实际数据情况和查询模式,重新调整数据分区和分桶策略,确保数据在集群中均匀分布,减少数据扫描范围。

(二)数据一致性保障

定期校验:迁移完成后,定期对 ClickHouse 和 Doris 中的数据进行一致性校验,可通过对比关键数据的统计信息(如记录数、聚合结果等),确保数据在迁移后及后续使用过程中保持一致。

增量同步:如果业务存在数据持续更新的情况,建立增量同步机制,确保 ClickHouse 中的新增或更新数据能够及时、准确地同步到 Doris 中,保证数据的实时性和一致性。

(三)监控与维护

集群监控:搭建完善的监控体系,对 Doris 集群的资源使用情况(CPU、内存、磁盘等)、查询性能、任务执行状态等进行实时监控,及时发现并解决潜在问题。

日志管理:合理管理 Doris 和相关工具的日志,通过分析日志信息,快速定位和排查迁移过程中或后续使用过程中出现的问题。

这份文档已涵盖多种迁移方式及后续优化等内容。若还想对某个迁移方式补充更多细节,或增加其他方面的内容,欢迎讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2374852.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WebSocket的原理及QT示例

一.WebSocket 介绍 1.概述 WebSocket 是一种在单个 TCP 连接上进行全双工通讯的协议&#xff0c;它在 2011 年被 IETF 定为标准 RFC 6455&#xff0c;并由 RFC7936 补充规范。与传统的 HTTP 协议不同&#xff0c;WebSocket 允许服务器和客户端之间进行实时、双向的数据传输&a…

vue3:十二、图形看板- echart图表-柱状图、饼图

一、效果 如图展示增加了饼图和柱状图,并且优化了浏览器窗口大小更改,图表随着改变 二、 饼图 1、新建组件文件 新增组件EchartsExaminePie.vue,用于存储审核饼图的图表 2、写入组件信息 (1)视图层 写入一个div,写入变量chart和图表宽高 <template><div ref…

2025年best好用的3dsmax插件和脚本

copitor 可以从一个3dsmax场景里将物体直接复制到另一个场景中 Move to surface 这个插件可以将一些物体放到一个平面上 instancer 实体器&#xff0c;举例&#xff1a;场景中有若干独立的光源&#xff0c;不是实体对象&#xff0c;我们可以使用instancer将他变成实体。 paste …

HAProxy + Keepalived + Nginx 高可用负载均衡系统

1. 项目背景 在现代Web应用中&#xff0c;高可用性和负载均衡是两个至关重要的需求。本项目旨在通过HAProxy实现流量分发&#xff0c;通过Keepalived实现高可用性&#xff0c;通过Nginx提供后端服务。该架构能够确保在单点故障的情况下&#xff0c;系统仍然能够正常运行&#…

5.12 note

Leetcode 图 邻接矩阵的dfs遍历 class Solution { private: vector<vector<int>> paths; vector<int> path; void dfs(vector<vector<int>>& graph, int node) { // 到n - 1结点了保存 if (node graph.size() - 1)…

跨时钟域(CDC,clock domain crossing)信号处理

参考视频&#xff1a; 数字IC&#xff0c;FPGA秋招【单bit信号的CDC跨时钟域处理手撕代码合集】_哔哩哔哩_bilibili 一、亚稳态 原因是&#xff1a;建立时间和保持时间没有保持住。然后在下图的红框里面&#xff0c;产生亚稳态。因为电路反馈机制&#xff0c;最后大概率会恢复…

OBS studio 减少音频中的杂音(噪音)

1. 在混音器中关闭除 麦克风 之外的所有的音频输入设备 2.在滤镜中增加“噪声抑制”和“噪声门限”

智能手表 MCU 任务调度图

智能手表 MCU 任务调度图 处理器平台&#xff1a;ARM Cortex-M33 系统架构&#xff1a;事件驱动 多任务 RTOS RTOS&#xff1a;FreeRTOS&#xff08;或同类实时内核&#xff09; 一、任务调度概览 任务名称优先级周期性功能描述App_MainTask中否主循环调度器&#xff0c;系统…

S7-1500——零基础入门2、PLC的硬件架构

PLC的硬件架构 一,西门子PLC概述二,CPU介绍三,数字量模块介绍四,模拟量模块介绍五,其他模块介绍一,西门子PLC概述 本节主要内容 西门子PLC硬件架构,主要内容包括PLC概述、组成、功能及S7-1500 demo的组成与安装演示。 介绍了PLC的定义、功能、应用场合,以及与继电器控…

【PmHub后端篇】Skywalking:性能监控与分布式追踪的利器

在微服务架构日益普及的当下&#xff0c;对系统的性能监控和分布式追踪显得尤为重要。本文将详细介绍在 PmHub 项目中&#xff0c;如何使用 Skywalking 实现对系统的性能监控和分布式追踪&#xff0c;以及在这过程中的一些关键技术点和实践经验。 1 分布式链路追踪概述 在微服…

利用“Flower”实现联邦机器学习的实战指南

一个很尴尬的现状就是我们用于训练 AI 模型的数据快要用完了。所以我们在大量的使用合成数据&#xff01; 据估计&#xff0c;目前公开可用的高质量训练标记大约有 40 万亿到 90 万亿个&#xff0c;其中流行的 FineWeb 数据集包含 15 万亿个标记&#xff0c;仅限于英语。 作为…

【RabbitMQ】应用问题、仲裁队列(Raft算法)和HAProxy负载均衡

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【中间件】企业级中间件剖析 一、幂等性保障 什么是幂等性&#xff1f; 幂等性是指对一个系统进行重复调用&#xff08;相同参数&#xff09;&#xff0c;无论同一操作执行多少次&#xff0c;这些请求…

软件设计师-错题笔记-系统开发与运行

1. 解析&#xff1a; A&#xff1a;模块是结构图的基本成分之一&#xff0c;用矩形表示 B&#xff1a;调用表示模块之间的调用关系&#xff0c;通过箭头等符号在结构图中体现 C&#xff1a;数据用于表示模块之间的传递的信息&#xff0c;在结构图中会涉及数据的流向等表示 …

C#简易Modbus从站仿真器

C#使用NModbus库&#xff0c;编写从站仿真器&#xff0c;支持Modbus TCP访问&#xff0c;支持多个从站地址和动态启用/停用从站&#xff08;模拟离线&#xff09;&#xff0c;支持数据变化&#xff0c;可以很方便实现&#xff0c;最终效果如图所示。 项目采用.net framework 4.…

【深度学习】目标检测算法大全

目录 一、R-CNN 1、R-CNN概述 2、R-CNN 模型总体流程 3、核心模块详解 &#xff08;1&#xff09;候选框生成&#xff08;Selective Search&#xff09; &#xff08;2&#xff09;深度特征提取与微调 2.1 特征提取 2.2 网络微调&#xff08;Fine-tuning&#xff09; …

视觉-语言-动作模型:概念、进展、应用与挑战(下)

25年5月来自 Cornell 大学、香港科大和希腊 U Peloponnese 的论文“Vision-Language-Action Models: Concepts, Progress, Applications and Challenges”。 视觉-语言-动作 (VLA) 模型标志着人工智能的变革性进步&#xff0c;旨在将感知、自然语言理解和具体动作统一在一个计…

一键解锁嵌入式UI开发——LVGL的“万能配方”

面对碎片化的嵌入式硬件生态&#xff0c;LVGL堪称开发者手中的万能配方。它通过统一API接口屏蔽底层差异&#xff0c;配合丰富的预置控件&#xff08;如按钮、图表、滑动条&#xff09;与动态渲染引擎&#xff0c;让工程师无需深入图形学原理&#xff0c;效率提升肉眼可见。 L…

智慧城市综合运营管理系统Axure原型

这款Axure原型的设计理念紧紧围绕城市管理者的需求展开。它旨在打破传统城市管理中信息孤岛的局面&#xff0c;通过统一标准接入各类业务系统&#xff0c;实现城市运营管理信息资源的全面整合与共享。以城市管理者为中心&#xff0c;为其提供一个直观、便捷、高效的协同服务平台…

Qwen智能体qwen_agent与Assistant功能初探

Qwen智能体qwen_agent与Assistant功能初探 一、Qwen智能体框架概述 Qwen&#xff08;通义千问&#xff09;智能体框架是阿里云推出的新一代AI智能体开发平台&#xff0c;其核心模块qwen_agent.agent提供了一套完整的智能体构建解决方案。该框架通过模块化设计&#xff0c;将L…

可视化图解算法37:序列化二叉树-II

1. 题目 描述 请实现两个函数&#xff0c;分别用来序列化和反序列化二叉树&#xff0c;不对序列化之后的字符串进行约束&#xff0c;但要求能够根据序列化之后的字符串重新构造出一棵与原二叉树相同的树。 二叉树的序列化(Serialize)是指&#xff1a;把一棵二叉树按照某种遍…