You need to enable JavaScript to run this app.
导航
从小文件导入
最近更新时间:2025.09.17 16:33:56首次发布时间:2022.12.19 15:10:59
复制全文
我的收藏
有用
有用
无用
无用

本文将介绍如何将小文件通过本地文件、对象存储、HDFS 等数据源导入至 ByteHouse。

功能概述

当您需要测试文件导入,或导入的文件体积较小时(如几 KB 至几十 MB 的小批量数据)时,推荐通过 INSERT INTO 语句完成导入,效率更优。 从导入效率来看,使用批式导入处理对象存储数据源,该过程需要调度 Spark 资源,即使是几 KB 的文件,也需分钟级导入。而 INSERT INTO 方式直接从对象存储读取数据写入 ByteHouse,无需依赖 Spark 资源调度,能快速完成导入。
ByteHouse 从小文件导入功能支持本地文件、对象存储、HDFS 数据源:

  • 从本地文件导入至 ByteHouse 时,需确保您使用的工具和文件均在本地,推荐通过 ClickHouse Client 连接 ByteHouse 并结合 INSERT INTO 语句完成导入,导入方式更简单便捷。
  • 从对象存储导入和从 HDFS 导入可使用能执行 SQL 语句的连接工具,您可使用 ByteHouse 企业版控制台的查询窗口或使用其他连接工具连接 ByteHouse,并使用 INSERT INTO 语句完成导入。连接 ByteHouse 操作详情请参考查询窗口连接集群

注意事项
  • 每次执行 INSERT INTO 时,会占用 ByteHouse 集群的 CPU 资源,可能与正在运行的查询任务争抢资源,导致查询响应延迟或性能下降。批式导入功能则采用旁路写入,使用 Spark 集群的 CPU 资源,因此不会发生抢占。
  • 如果直接向 Distributed 分布式表执行 INSERT INTO(如下文示例场景),当集群分片数大于 1 时,数据需在分片间进行路由分发,会产生额外的网络传输和数据处理开销,导致导入性能较差。建议您将源数据按分片规则拆分后,分别向各节点的本地表(即示例中的 Local 表)执行导入,可减少资源消耗,提升导入效率。
  • 基于上述资源占用特性与性能局限,从小文件导入方式仅适合于导入测试,不适合于实际生产。如果您需要导入大批量数据可参考批式导入流式导入

基本语法

从本地文件导入

clickhouse client \
  --host <host> \
  --user <user> \
  --password <password> \
  --query "INSERT INTO <database_name>.<table_name> FORMAT format SETTINGS key1=value1, key2=value2" \
  < File_Name.csv \

您也可以使用 Cat 命令:

cat File_Name.csv | clickhouse-client \
    --host <host> \
    --user <user> \
    --password <password> \
    --query="INSERT INTO <database_name>.<table_name> FORMAT format SETTINGS key1=value1, key2=value2";

参数说明

参数项

配置说明

host

ByteHouse 集群的网络地址。您可登录 ByteHouse 企业版控制台,在集群管理 > 集群列表 > 集群名称 > 连接集群中,查看并复制 ClickHouse Client 卡片中的 host 地址。
Image

user

ByteHouse 账户名。您可登录 ByteHouse 企业版控制台,在集群管理 > 集群列表 > 集群名称 > 连接集群中,查看并复制 ClickHouse Client 卡片中的 user 信息。

password

ByteHouse 连接密码。您可登录 ByteHouse 企业版控制台,单击右上角 ByteHouse 个人中心,单击账号管理,复制集群连接密码。
Image

query

设置为 INSERT INTO 语句。

  • INSERT INTO <database_name>.<table_name>:指定需导入的数据库和表名。
  • FORMAT:指定为数据源文件的格式,当前支持的格式请参见输入和输出数据的格式
  • SETTINGS:设置 settings 参数,用于配置 CSV 数据的实际格式,灵活适配数据读写需求。当前支持配置的 settings 参数请参见Settings 配置

File_Name

需导入的文件路径及文件名。

从对象存储导入

INSERT INTO <database_name>.<table_name>
SELECT * FROM s3(
    path, 
    access_key_id,
    secret_access_key,
    format,
    structure,
    [compression]
)
[SETTINGS key1=value1, key2=value2];

参数说明

参数项

配置说明

database_name

目标数据库名称。

table_name

目标数据表名称。

path

指定对象存储中源表的路径,示例如下:

https://{bucket_name}.endpoint/file_path/file

如果您使用的是 TOS,可通过 TOS 控制台 > 桶列表 > 桶名称 > 文件列表 > 文件名后的详情按钮,查看并复制 URL,并将域名更换为 S3 Endpoint 域名,推荐使用内网域名,详情参见火山引擎 TOS 支持的地域和访问域名。示例如下:

https://{bucket_name}.tos-s3-{region}.ivolces.com/file_path/file

access_key_id

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

secret_access_key

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

format

设置为源文件格式,如 CSV。当前支持的格式请参见输入和输出数据的格式

structure

设置为源表结构,包括列名和列类型。示例: 'column1_name column1_type, column2_name column2_type, ...'

compression

可选配置,指定数据的压缩格式,支持 none, gzip/gz, brotli/br, xz/LZMA, zstd/zst

SETTINGS

可选配置,设置 settings 参数,用于配置 CSV 数据的实际格式,灵活适配数据读写需求。当前支持配置的 settings 参数请参见Settings 配置

从 HDFS 导入

INSERT INTO <database_name>.<table_name>
SELECT * 
FROM hdfs(
    'path', 
    'format',                    
    'structure'
)
[SETTINGS key1=value1, key2=value2];

参数说明

参数项

配置说明

database_name

目标数据库名称。

table_name

目标数据表名称。

path

设置为 HDFS 文件完整路径,格式为 hdfs://host:port/file_path/file_name

  • host:HDFS 集群 NameNode 的 IP 或主机名,示例:192.168.1.100
  • port:HDFS 默认端口(HA 集群通常 8020,非 HA 集群 9000);
  • file_path/file_name :文件路径,示例:/user/data/user_202509.csv

format

设置为源文件格式,如 CSV。

structure

设置为源表结构,包括列名和列类型。示例: 'column1_name column1_type, column2_name column2_type, ...'

SETTINGS

可选配置,设置 settings 参数,用于配置 CSV 数据的实际格式,灵活适配数据读写需求。当前支持配置的 settings 参数请参见Settings 配置

Settings 配置

在执行 SQL 语句时,您可根据 CSV 数据的实际格式,按需添加以下 Settings 配置项,灵活适配数据读写需求。

Settings 配置项

默认值

描述

format_csv_delimiter

,

指定 CSV 数据中字段的分隔符字符。如果设置为字符串,该字符串必须长度为 1。

format_csv_allow_single_quotes

1(true)

是否允许使用单引号('...')包裹字段内容。如果设置为 true,表示允许单引号内的字符串。

format_csv_allow_double_quotes

1(true)

是否允许使用双引号("...")包裹字段内容。如果设置为 true,表示允许双引号内的字符串。

format_csv_write_utf8_with_bom

0(false)

是否在输出的 CSV 文件开头写入 UTF-8 BOM(字节顺序标记)。如果设置为 true,将在输出的开头写入 BOM。

output_format_csv_crlf_end_of_line

0(false)

输出 CSV 时是否使用行尾符 \r\n,否则使用 \n

output_format_csv_null_representation

\N

指定输出时用于表示 NULL 值的字符串。默认为 \N,可自定义为其他字符串(如 NULL)。

input_format_csv_unquoted_null_literal_as_null

0(false)

是否将未加引号的文本 NULL 视为 \N 值。若关闭,则视为普通字符串。

input_format_csv_enum_as_number

0(false)

导入 CSV 时,是否将枚举值解释为其对应的枚举索引 \N

input_format_csv_arrays_as_nested_csv

0(false)

是否将数组字段解析为嵌套 CSV 格式。例如:"Hello", "world", "42 TV" 被解析为数组元素;支持使用双引号和转义。数组外层的方括号可省略。

使用示例

创建 ByteHouse 目标数据库、表

在 ByteHouse 中创建目标数据库、表,请确保目标表与源表结构一致,操作详情请参见新建数据库/表
本文示例以 HaMergeTree 表为例,建表语句如下:

-- 创建数据库
CREATE DATABASE IF NOT EXISTS test_db

-- 创建 Local 本地表
CREATE TABLE IF NOT EXISTS test_db.test_table_local ON CLUSTER default_cluster
(
    `id` String,
    `name` String,
    `date` Date
)
ENGINE = HaMergeTree('/clickhouse/tables/test_db/test_table_local/{shard}', '{replica}')
ORDER BY id;

-- 创建 Distributed 分布式表
CREATE TABLE IF NOT EXISTS test_db.test_table ON CLUSTER default_cluster
AS test_db.test_table_local
ENGINE = Distributed('default_cluster', 'test_db', 'test_table_local', rand());

从本地文件导入

准备工作

安装 ClickHouse Client 工具,点此下载

操作步骤

  1. 准备本地文件 test.csv,并写入数据如下。确保本地 CSV 文件的字段顺序与目标表的字段顺序一致。

    $ cat /test.csv
        A001,Amy,2023-01-01
        A002,Bob,2023-01-02
        A003,Charles,2023-01-03
    
  2. 使用 ClickHouse Client 向目标表写入数据。

    cat test.csv | clickhouse-client \
        --host 2xxxxxxxxxxxxxxxxx.bytehouse-ce.ivolces.com \
        --user demo_user \
        --password Mt**************  \
        --query="INSERT INTO test_db.test_table_local FORMAT CSV";
    
  3. 查询是否写入成功。

    SELECT * FROM test_db.test_table;
    

从对象存储导入

本示例将演示如何使用 ClickHouse s3() 函数,将本地文件中的数据写入到准备工作章节创建的 ByteHouse 表中。

准备工作

在开始操作前,请确保您已经具备您使用的对象存储桶的访问权限:

操作步骤

  1. 构建 Schema 映射。此步骤用于获取目标表的字段名和字段类型,确保源数据与目标表结构匹配,避免导入时因结构不匹配导致失败。

    SELECT arrayStringConcat(groupArray(concat(name, ' ', type)), ', ')  
    FROM system.columns 
    WHERE DATABASE = '<database_name>' AND TABLE = '<table_name>'
    
  2. 从对象存储中导入数据至 ByteHouse。

    INSERT INTO test_db.test_table_local
    SELECT *
    FROM s3(
        'https://bucket.endpoint/file_path/test_outfile.csv', 
        'AK***************',                                 
        'aBc********************',                
        'CSV',                                          
        '(id String, name String, date Date)',  
        'none',                                           
    );
    
  3. 查询是否写入成功。

    SELECT * FROM test_db.test_table;
    

从 HDFS 导入

本示例将演示如何使用 ClickHouse hdfs() 函数,将本地文件中的数据写入到准备工作章节创建的 ByteHouse 表中。

准备工作

在开始操作前,请确保您已经获取 HDFS 文件的访问路径,且具备该路径的访问权限。

操作步骤

  1. 从 HDFS 中导入数据至 ByteHouse。

    INSERT INTO test_db.test_table_local 
    SELECT * 
    FROM hdfs(
        'hdfs://192.168.x.xxx:8020/user/data/202509_user.csv',
        'CSV',
        '(id String, name String, date Date)'
    );
    
  2. 查询是否写入成功。

    SELECT * FROM test_db.test_table;
    

常见问题

Code: 27

如果您在使用中遇到以下报错:

Code: 27, e.displayText() = DB::ParsingException:Cannot parse input: expected '\\N' before: ... (version 21.8.7.1) 
  • 问题原因
    出现这一报错的原因,一般是由于 CSV 文件中的字符串存在不被单引号或双引号包围,且内容中存在反斜杠 \,如 aaa,bbb,cc\c,这种情况会被 ByteHouse 视作特殊字符。
  • 解决方法
    • 在数据源中,将字符串都置于双引号或单引号中,这样 ByteHouse 会认为反斜杠是字符串的一部分。
    • 在插入时设置 input_format_null_as_default = 0,即 ByteHouse 不再识别 \NNull。但此种方案将导致无法导入 Null 值。