You need to enable JavaScript to run this app.
文档中心
文档控制台
注册
ByteHouse云数仓版

ByteHouse云数仓版

复制全文
下载 pdf
搬站工具
迁移 ClickHouse 至 ByteHouse
复制全文
下载 pdf
迁移 ClickHouse 至 ByteHouse

ByteHouse 云数仓支持通过脚本工具,以离线方式将您存储在 ClickHouse 中的数据快速迁移至 ByteHouse 云数仓并投入使用,助力实现数据的统一管理与开发。本文将详细介绍 ClickHouse 数据库表及数据向 ByteHouse 云数仓的迁移方法。

功能概述

将 ClickHouse 数据迁移至 ByteHouse 云数仓依赖于 ByteHouse 提供的迁移脚本:ClickHouse 数据导出脚本和数据导入脚本。在迁移时,

  1. 使用 ClickHouse 数据导出脚本将数据从 ClickHouse 导出至对象存储;
  2. 使用基于 ByteHouse S3 外表功能开发的数据导入脚本完成从对象存储的数据导入。

脚本名称

能力说明

ByteHouse 自研 ClickHouse 数据导出脚本

  • 断点续传:能够精准记录导入状态,对于已成功执行的导入任务不再重复执行,若任务失败则支持回滚操作,保障迁移过程的稳定性与连续性。
  • 并发导出:支持并发导出,提升导出效率。
  • 通用导出能力:具备通用导出能力,适配多种数据场景。
  • 进度条展示:通过进度条直观展示导出进度。

ByteHouse 自研数据导入脚本

  • 断点续传:能够精准记录导入状态,对于已成功执行的导入任务不再重复执行,若任务失败则支持回滚操作,保障迁移过程的稳定性与连续性。
  • 并发执行:支持外表创建和导入 SQL 的并发处理,可有效提升迁移效率,缩短整体迁移时间。
  • 多表多库支持:可同时对多个数据库中的多张表进行迁移操作,满足复杂数据环境下的迁移需求。
  • 外表分区过滤导入:支持针对单表设置分区筛选策略,仅导入符合条件的分区数据,减少不必要的数据处理。
  • 外表存储格式配置:支持单表粒度的存储格式自定义,可根据实际业务需求选择合适的存储格式。
  • 导入重试能力:当导入任务出现异常时,支持自动或手动重试,提高任务成功率。
  • 单表操作支持:支持单表粒度的 insert into(插入)及 insert overwrite(覆盖)操作,满足不同的数据导入需求。
  • dry-run 功能:可提前运行脚本进行检查,验证脚本的正确性,避免因脚本问题导致迁移失败。
  • N 级分区外表:对于 Hive 分区表,支持按照 Hive 分区表模式,为单表配置粒度化的分区规则,灵活适配不同的数据分区场景。

迁移流程

从 ClickHouse 迁移至 ByteHouse 的流程主要包括下三大步骤,您可按照下文详细操作说明迁移数据。

  1. 准备目标表,在 ByteHouse 中创建迁移所需的目标表。
  2. 从 ClickHouse 导出数据到对象存储服务,并检查导出至对象存储服务中的数据和目录是否符合预期。
  3. 将数据从对象存储服务导入至 ByteHouse,并检查数据一致性。

Image

使用限制

如果您的迁移场景符合以下任一条件,请联系 ByteHouse 团队处理:

  • 单表大小超过 10 亿行;
  • 计算组规格较小(规格为 M 或以下规格),同时表大小超过 1 亿行。

注意事项
  • 迁移过程中,目标数据库与源数据库、对象存储服务间的网络互通且网络环境稳定。
    • 通常情况下,ClickHouse、对象存储服务、ByteHouse 间需通过公网传输,请确保网络环境稳定;若您已搭建专线,可切换为私网传输,此时需确保专线配置完成且网络环境稳定。
    • 使用火山引擎对象存储服务 TOS 传输到 ByteHouse 时,需确保 TOS 与 ByteHouse 实例处于相同地域,以保障数据传输效率并避免跨地域访问产生额外费用。
  • 迁移过程中使用数据服务可能涉及费用,请以产品的实际计费为准。

准备工作
  1. 获取 ClickHouse、对象存储服务、ByteHouse 的连接信息,包括域名、端口号、账号、密码、Access Key ID(AK)、Secret Access Key(SK)等。

  2. 为您使用的 ClickHouse、ByteHouse 账号配置对象存储服务的全读写权限。

  3. (可选)安装 Python ClickHouse driver,用于导出 ClickHouse 数据时连接 ClickHouse 集群。如果您的环境中已安装 ClickHouse Client 命令行工具,可跳过该步骤,并在导出数据时使用 run_sql_mode=cli

    # 使用 pip 安装
    pip install tqdm clickhouse-driver
    
    # 使用 pip3 安装
    pip3 install tqdm clickhouse-driver
    
  4. 确认您已在 ByteHouse 中配置默认写计算组,该计算组用于数据 merge 操作。您可登录 ByteHouse 控制台,单击顶部租户管理,在参数设置页签下,设置默认写计算组。
    如果您的 Bytehouse 计算组需要设置特定的兼容性配置,请联系 ByteHouse 团队。
    Image

  5. 如果您对时区有特殊需求,可联系 ByteHouse 团队设置租户级别的 session timezone 为指定的时区。默认情况下,您在火山引擎中使用的 ByteHouse 服务使用东八区,在 AWS 中使用的 ByteHouse 服务使用 UTC 时区。

步骤一:准备目标表

请确保 ClickHouse 源数据库/表已准备就绪,且在 ByteHouse 中创建了对应的目标数据库/表,可参考数据库管理。ByteHouse 也提供了建表最佳实践,详情请参考ByteHouse 建表配置最佳实践ByteHouse 唯一键表最佳实践
如果您需要创建的表数量较多,可提交工单或联系 ByteHouse 团队。

步骤二:从 ClickHouse 导出数据到对象存储服务
  1. 下载迁移至对象存储服务所需的 ByteHouse 自研 ClickHouse 数据导出脚本文件。下载后,请将该脚本文件存储至您自定义的路径,并记录该路径,用于后续执行脚本时配置。

    data-migrator-clickhouse-to-s3.py
    未知大小

    该脚本提供了两种方式连接您的 ClickHouse 集群,您可通过在下述步骤 2 中的 ini 文件中设置 run_sql_mode 参数,以使用对应的连接方式。

    • 方式一:通过 Python ClickHouse driver 连接
      默认连接方式,需将 run_sql_mode 参数设置为 driver,适用于环境中不支持安装 ClickHouse Client 的场景。
    • 方式二:通过执行环境的中的 ClickHouse Client 执行文件连接
      需将 run_sql_mode 参数设置为 cli。如果您的环境已安装 ClickHouse Client 命令行工具,可使用该方式连接。
  2. 在 ClickHouse 数据导出脚本同一路径下,创建并配置 ini 文件。本文示例中将 ini 文件命名为 config-template-export.ini
    请使用实际的 ClickHouse 连接信息、对象存储的目标存储路径、数据迁移参数值替换示例中的占位符或示例参数值,以便脚本正确执行数据导出操作。参数详细配置信息请参见参数说明。

    适用于对象存储服务为火山引擎对象存储 TOS。

    dryrun=0
    # 设置连接 ClickHouse 集群的方式,默认值为 driver,表示使用 Python ClickHouse driver 连接
    # 如果您的环境已安装 ClickHouse Client,可将设置为 run_sql_mode=cli,脚本将使用 ClickHouse Client 连接
    run_sql_mode=driver
    #### ClickHouse 的连接信息
    # ClickHouse 的 host 节点,可以使用逗号分割选择多个节点
    clickhouse_host=127.0.0.1
    clickhouse_port=9000
    clickhouse_user=default
    clickhouse_password={your_clickhouse_password}
    
    #### 对象存储连接信息
    s3_access_key={tos_access_key}
    s3_secret_key={tos_secret_access_key}
    s3_url=https://{bucket_name}.tos-s3-{region}.volces.com/{dir_name}
    
    #### 导出数据表的相关信息
    database_name={database_name}
    table_names={table_name1},{table_name2},...
    ;field_rules=
    ;export_field_rules=
    
    #### 切分方式
    # 分区级别分隔参数
    split_in_partition=1
    selected_partitions=
    # 全局/分区分割(split)参数,可以基于分区(partition)/整表再进行分批导出
    split_count=-1
    # 作为 hash 进行分割的列,可以配置多个列,按照逗号隔开,按照顺序选择存在表中的数据,选择的优先级:在 orderby 配置中的离散列,int 或者 string 类型的列
    split_column=
    split_function=
    
    #### 查询的额外条件
    where=
    limit=
    
    #### 断点续传能力,可以控制成功后的导出 SQL 不再执行。
    # 是否清理状态。1 为清理,默认为 0 不清理
    empty_status=0
    
    #### 额外参数
    # 最大重试次数
    max_retries=1
    # 每次重试延迟,单位为秒(s)
    retry_delay_seconds=1
    # SQL 的 Settings,目前建议配置为 timeout 的一些配置,单位为秒(s)。
    # 您也可以按需配置 s3_truncate_on_insert=true,表示如果存在原有文件,系统将删除这些,即覆盖原有文件。
    s3_insert_settings=send_timeout=3600, receive_timeout=3600, max_execution_time=3600,output_format_json_quote_64bit_integers=0
    # 文件格式及压缩配置
    file_format=Parquet
    data_compression_method=none
    # 需要导出的 ClickHouse 表引擎
    filter_tables_by_engine=MergeTree
    
    #### 并发参数,控制导出 SQL 在 ByteHouse 执行的并发
    parallelism=8
    

    配置 Key

    类型

    描述

    dryrun

    int

    配置试运行开关,参数默认值:0;可选取值:0或1。其中 0 代表关闭试运行,1 代表启用试运行。

    run_sql_mode

    string

    设置连接 ClickHouse 集群的方式,默认值为 driver,表示使用 Python ClickHouse driver 连接。
    如果您的环境已安装 ClickHouse Client,可将设置为 cli,脚本将使用 ClickHouse Client 连接。

    clickhouse_host

    string

    ClickHouse 的地址,可以用逗号分割选择多个 shard 节点。

    clickhouse_port

    string

    ClickHouse 的端口,配置为 9000。

    clickhouse_user

    string

    ClickHouse 的用户名。

    clickhouse_password

    string

    ClickHouse 的密码。

    s3_access_key

    string

    存储导出文件的对象存储服务的 Access Key ID。
    如果您使用的是火山引擎 TOS,获取方式可参考 Access Key(密钥)管理

    s3_secret_key

    string

    存储导出文件的对象存储服务的 Secret Access Key。
    如果您使用的是火山引擎 TOS,获取方式可参考 Access Key(密钥)管理

    s3_url

    string

    导出文件在对象存储中的目标存储目录。格式示例如下:

    • 导出到 TOS:

      # 公网
      https://{bucket_name}.tos-s3-{region}.volces.com/some-dir
      # 私网
      https://{bucket_name}.tos-s3-{region}.ivolces.com/some-dir
      
    • 导出到其他对象存储服务:

      # AWS S3
      s3_url=https://{bucket_name}.s3.{region}.amazonaws.com/some-dir
      # MinIO 或者其他对象存储
      s3_url=http://{host}:{port}/{bucket_name}/some-dir
      

    database_name

    string

    ClickHouse 需导出的数据库名称。

    table_names

    string

    ClickHouse 数据库中需导出的表名称,如果需要导出多张表,可使用逗号分开。如果使用星号(*),则代表导出数据库中的所有表。

    field_rules

    string

    用于对特殊类型的数据进行导出预处理,可使用当前默认值,非特殊情况无需配置。如果有多个参数,可使用分号连接。
    默认规则:针对不同位宽的 groupBitmap 聚合函数类型(如 AggregateFunction(groupBitmap, UInt8)UInt256 ),统一通过 bitmapToArray($Field$) 函数将位图数据转换为数组格式。
    当前已配置的默认值如下:
    AggregateFunction(groupBitmap, UInt8):bitmapToArray($Field$);AggregateFunction(groupBitmap, UInt16):bitmapToArray($Field$);AggregateFunction(groupBitmap, UInt32):bitmapToArray($Field$);AggregateFunction(groupBitmap, UInt64):bitmapToArray($Field$);AggregateFunction(groupBitmap, UInt128):bitmapToArray($Field$);AggregateFunction(groupBitmap, UInt256):bitmapToArray($Field$)

    export_field_rules

    string

    用于定义特殊类型数据导出后的目标类型,可使用当前默认值,非特殊情况无需配置。如果有多个参数,可使用分号连接。
    默认规则:针对不同位宽的 groupBitmap 聚合函数类型(如 AggregateFunction(groupBitmap, UInt8)UInt256),指定导出后的数据类型为对应位宽的数组(如 Array(UInt8)Array(UInt256))。
    当前已配置的默认值如下:
    AggregateFunction(groupBitmap, UInt8):Array(UInt8);AggregateFunction(groupBitmap, UInt16):Array(UInt16);AggregateFunction(groupBitmap, UInt32):Array(UInt32);AggregateFunction(groupBitmap, UInt64):Array(UInt64);AggregateFunction(groupBitmap, UInt128):Array(UInt128);AggregateFunction(groupBitmap, UInt256):Array(UInt256)

    split_in_partition

    int

    设置是否按照分区(partition)分割(split)导出。可设置为 1 或 0。

    • 默认设置为 1,系统将按照分区分割导出数据。
    • 设置为 0 时,系统将不按照分区分割导出,按照全表进行导出。

    说明

    建议配置取值为默认值 1,该配置将以分区形式导出数据,可提升数据导出效率。

    selected_partitions

    string

    可指定若干分区 ID 并以英文逗号分隔导出,该参数需配合split_in_partition=1使用;
    无需指定具体导出分区时,该参数无需配置。
    配置取值仅支持partition_id,不可直接填写分区名称。

    split_count

    int

    表数据导出时拆分生成多文件,提升导出速率,配置作用域支持全表、分区两种级别。
    默认值:1000000

    说明

    • 参数取值小于 0 时,关闭文件拆分功能。
    • 导出数据推荐基于ORDER BY首列排序,优先选择基数较大的字段。

    split_column

    string

    一般情况下,该参数无需设置。
    默认:id,若id 不存在,则选择表中第一列。
    如果出现数据导出时性能不佳的情况,可使用该参数指定用于数据分割的列。导出大量数据时,脚本工具将利用列的哈希值将数据分割成多个部分,加速导出。支持配置多个列,多个列名之间用逗号分隔,系统将按照顺序选择存在表中的数据,具体优先级如下:

    • 优先级 1:优先选择在 Order By 中配置的离散列;
    • 优先级 2:其次选择 int 或者 string 类型的列;
    • 默认列:若以上均无,则默认选择 id。

    split_function

    string

    默认值:空
    split_function为独立配置项,与split_countsplit_column配置逻辑相互独立;支持自定义函数表达式,数据表或分区拆分时将依据该表达式执行拆分逻辑,在超大表导出场景下具备优异的执行效率。
    示例
    对于一张按月 toYYYYMM(eventDate) 分区、规模达到几百亿数据的表,导出时可配置 toYYYYMMDD(eventDate) 作为 split 表达式,以提升导出效率。

    where

    string

    可使用该参数为某张表设置 filter 条件。
    默认值为空,如果您需要为不同的表设置不同的筛选条件,请按照 table_names 进行细分,并为每张表生成新的配置文件执行导出任务。

    limit

    string

    可使用该参数为某张表配置限制条件。
    默认值为空,如果您需要为不同的表设置不同的筛选条件,请根据 table_names 细分,并为每张表生成对应的配置文件执行导出任务。

    empty_status

    int

    断点续传能力开关,用于设置导出时是否参考之前的断点信息。默认为 0,表示参考之前的断点信息,即开启断点续传。设置为 1 时,本次导出时将不参考之前的断点信息。

    max_retries

    int

    失败后最大的重试次数,默认值为 1。

    retry_delay_seconds

    int

    每次重试延迟多久,默认值为 5,单位:秒。

    file_format

    string

    导出文件的格式,默认格式为 JSONEachRow,建议设置为 JSONEachRow 或 Parquet。

    data_compression_method

    string

    导出文件的压缩方式,默认设置gzip。

    说明

    该参数不建议修改。

    s3_insert_settings

    string

    该设置用于避免导出超时,建议使用默认值:

    send_timeout=3600, receive_timeout=3600, max_execution_time=3600,output_format_json_quote_64bit_integers=0,s3_truncate_on_insert=true
    

    参数说明如下:

    • send_timeout:数据传输超时设置。建议使用默认值 3600,单位为秒。
    • receive_timeout:数据接收超时设置。建议使用默认值 3600,单位为秒。
    • max_execution_time:单次查询最长执行时间。建议使用默认值 3600,单位为秒。
    • output_format_json_quote_64bit_integers:控制 ClickHouse 以 JSON 格式输出时,是否用双引号包裹 64 位整数值。设置为 0 时,表示不包裹,输出数字格式;设置为 1 时,表示包裹,输出字符串格式。建议设置为 0。
    • s3_truncate_on_insert=true:导入时是否清空对象存储服务的目录。设置为 true 时,则会在每次导入时,清空对象存储服务的目录。建议设置为 true。

    filter_tables_by_engine

    string

    设置为需要导出的 ClickHouse 表引擎,支持设置为 MergeTree 和 ReplacingMergeTree。默认值为 空。

    parallelism

    int

    设置并发导出的参数,代表并发数。默认为 4。

  3. 运行 Python 脚本文件,即可将 ClickHouse 中的数据导出至对象存储服务中。
    运行前,请确保当前工作目录为脚本所在目录,或使用绝对路径指定脚本位置。

    python3 data-migrator-clickhouse-to-s3.py config-template-export.ini 
    
  4. ClickHouse 数据导出后,检查对象存储中的导出的数据和目录是否符合预期。
    使用上述步骤导出的数据文件将以按照以下目录结构存储在对象存储中,您可按照以下示例路径,在您使用的对象存储服务中查看目录和数据是否符合预期。该示例展示了 AWS S3 的路径信息,TOS 和 MinIO 路径类似。

    https://{bucket_name}.s3.{region}.amazonaws.com/ck-to-bytehouse/{database_name}/{table_name}/{database_name}_{table_name}_{partition_id}_{hash_num_order}.JSONEachRow.gz 
    

步骤三:从对象存储服务导入到 ByteHouse

使用 ByteHouse 自研数据导入脚本将导出的数据从对象存储服务导入到 ByteHouse。ByteHouse 自研导入脚本利用 S3 外表功能实现数据迁移:通过创建 S3 外表直连对象存储读取数据,并自动同步至目标内表完成导入。详细操作请参考数据导入
迁移完成后,您可以在 ByteHouse 中创建表、使用并查询系统表,ClickHouse 与 ByteHouse 表引擎、系统表映射关系请参见相关参考:表引擎及系统表映射关系

常见问题

OPENSSL_internal:CERTIFICATE_VERIFY_FAILED

如果您在使用过程中遇到 OPENSSL_internal:CERTIFICATE_VERIFY_FAILED 报错,这是由于 TLS 版本低于 v1.3,本地的 OpenSSL 模块或系统 CA 证书链不被目标站点信任导致的。您可通过以下两种方式解决:

  • 方式一升级 TLS
    您可根据您使用的操作系统,查找相应的升级教程,将 TLS 升级至 v1.3 及以上版本。
  • 方式二使用 http 协议
    在步骤二中,设置数据导出配置文件中的 s3_url 参数时,使用 http 协议,例如 s3_url=http://{bucket_name}.tos-s3-{region}.volces.com/{dir_name}

相关参考:表引擎及系统表映射关系

ByteHouse 与 ClickHouse 表引擎及系统表映射关系如下:

表引擎对应关系

ClickHouse 中常用的表引擎包含 MergeTree、ReplicatedMergeTree + Distributed、SummingMergeTree、AggregatingMergeTree、CollapsingMergeTree、VersionedCollapsingMergeTree、ReplacingMergeTree,ByteHouse 表引擎为自研的 CnchMergeTree 表引擎,对应关系如下:

ClickHouse 表引擎

ByteHouse 表引擎

MergeTree

直接替换为不带 UniqueKey 的 CnchMergeTree。需要注意的是,CnchMergeTree 当前只支持 partition-level 的 TTL,不支持 row-level 的 TTL,但 partition-level 的 TTL 是绝大多数表的建表选择。

ReplicatedMergeTree + Distributed

SummingMergeTree

建议改成普通表后手动改查询计算 sum。

AggregatingMergeTree

方案一
通过同步或异步物化视图替换:

  1. 使用同步物化视图 + CnchAggregatingMergeTree:流式写入,每个 push 都会产生一个数据块(part),需要 CnchAggregatingMergeTree 在 merge 过程合并。该方案要求基表不能为 unique 表。
  2. 异步物化视图:分区级别聚合。需要综合考虑刷新数据量以及预期返回时间的要求,一般要求基表与目的表分区对齐,基表使用离线导入方式,实时导入刷新成本较高,join 的场景维表更新频率较低。

方案二
改写为普通 CnchMergeTree 表,查询需要业务主动改写 SQL 添加 agg。

CollapsingMergeTree

可替换为带 UniqueKey 的 CnchMergeTree,即 unique 表。
UniqueKey 为原表的 OrderBy Key。
原表的 sign 列替换为 Unique 表的 _delete_flag_ 隐式列(不需要显式定义)。原表的 sign = 1 对应为 Unique 表的 _delete_flag_ = 0(新增),原表的 sign = -1 对应为 Unique 表的 _delete_flag_ = 1(删除)。
实际操作中,根据 UniqueKey 新增和更新行时,由于 _delete_flag_ 默认值为 0,您无需显式指定 _delete_flag_ 的数值,如有必要,也可以显式指定 _delete_flag_ = 0;根据 UniqueKey 删除行的时候,必须要显式指定 _delete_flag_ = 1

VersionedCollapsingMergeTree

可替换为带 UniqueKey 的 CnchMergeTree,即 unique 表。
UniqueKey 为原表的 OrderBy Key。
version 列使用方式如下: CnchMergeTree(version)。
sign 列的替换和使用和 CollapsingMergeTree 一致。

ReplacingMergeTree

可替换为 CnchMergeTree + Unique key。原表的ORDER BY作为UNIQUE KEY。建表时可使用可选参数:veris_deleted

  • ver:可等价替换为 unique 表的版本字段。Cnch Unique 表支持将表中的某个字段指定为版本字段。引擎保证写入相同 key 的数据时,只有数据版本 >= 已有版本时,才会进行覆盖。版本字段支持所有UInt类型和Data/DateTime,且不能为 Nullable。参考文档:ByteHouse 建表配置最佳实践
  • is_deleted: 可用 unique 表的 _delete_flag_ 代替。原表的 is_deleted=1(删除),对应 _delete_flag_=1;原表的 is_deleted=0(保留),对应 _delete_flag_=0
    ClickHouse 的 is_deleted 字段为显式列,且仅能与 ver 字段同用。Unique 表没有该限制,_delete_flag_ 为隐式列。

注意

不推荐在 ByteHouse 中使用 MySQL、MongoDB 等引擎。

系统表对应关系

ByteHouse CDW 陆续支持 ClickHouse 系统表,使用前请先确认 ByteHouse 的引擎版本是否支持对应的系统表。您可通过 ByteHouse 控制台 > 租户管理 > 基本信息 路径,查看引擎版本。
Image

ClickHouse 系统表

ByteHouse 系统表

ByteHouse 引擎版本要求

说明

system.query_log

bh_system.query_log

v2.1

可使用bh_system.query_log 查询历史记录。使用前,请通过 ByteHouse 控制台 > 审计日志 > SQL 审计 路径,开启详细日志。
Image

说明

如果您的界面中未找到开启详细日志入口,可联系 ByteHouse 团队添加白名单。

system.databases

system.databases

v2.1

包含了当前存在的所有数据库的信息,如数据库名称、创建时间等。

system.tables

system.cnch_tables

v2.2

包含了数据库中所有表的信息,如表名称、所属数据库、引擎类型等。
不建议在查询时省略 databasename 列的筛选条件(如 SELECT *),或查询包含 total_rowstotal_bytes 列,类似查询会导致消耗比较多的时间计算精确元信息。

system.columns

system.cnch_columns

v2.2

包含了数据库中所有表的列的信息,如列名称、数据类型、表名称等。

system.functions

system.functions

v2.1

包含了 ClickHouse 支持的所有函数的信息,如函数名称、参数类型等。

system.mutations

system.mutations

v2.2

用于存储正在进行的数据变更操作(如 UPDATE、DELETE、ALTER)的信息。
只能返回响应请求的 server 的 mutations 进度结果,如果需要完整返回结果需要重新设计和改动。

system.parts

system.cnch_parts_info

v2.2

包含有关 MergeTree 表中所有数据块(parts)的信息。

最近更新时间:2026.06.04 14:36:40
这个页面对您有帮助吗?
有用
有用
无用
无用