You need to enable JavaScript to run this app.
导航

从小文件导入

最近更新时间2024.03.26 10:50:54

首次发布时间2022.12.19 15:10:59

在测试文件导入或导入文件不大的场景,您可以使用 clickhouse-client 进行直接的文件导入。相比批式导入,对象存储导入方式因其需要调度 Spark 资源而会比较慢(即便几 kb 的文件也需要分钟级导入),而直接通过 Insert into导入会很快。
在参考此示例前,需注意以下事项:

  • 每次 Insert into 都会占用 ByteHouse 集群的 CPU 资源,会抢占正在进行的查询;而批式导入功能则采用旁路写入,使用 Spark 集群的 CPU 资源,因此不会发生抢占。
  • 示例直接插入到了 Distributed 表,在集群 > 1 个分片的情况下,这种方式性能较差。一般建议拆分数据后分别插入不同节点的 local 表(即示例中的 HaMergeTree 表)。
  • 基于上述两点,这种方式仅适合于导入测试,不适合于实际生产。

导入步骤如下:

从本地文件导入

基本语法

clickhouse client \
  --host <host> \
  --user <user> \
  --port <port> \
  --query "INSERT INTO cell_towers FORMAT CSVWithNames" \
  < File_Name.csv \

或者使用 Cat 命令

cat File_Name.csv | clickhouse-client \
    --host <host> \
    --user <user> \
    --port <port> \
    --query="INSERT INTO cell_towers FORMAT CSVWithNames";

相关配置

可以按需在执行的 SQL 语句中加入以下Settings配置项。

配置

默认值

描述

format_csv_delimite

,

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

format_csv_allow_single_quotes

1

如果设置为true,允许单引号内的字符串。

format_csv_allow_double_quotes

1

如果设置为true,允许双引号内的字符串。

format_csv_write_utf8_with_bom

0

如果设置为true,将在输出的开头写入BOM。

output_format_csv_crlf_end_of_line

0

如果设置为true,CSV格式的行尾将是\r\n而不是\n。

output_format_csv_null_representation

\N

在CSV格式中自定义NULL表示,默认 \N 为 NULL。

input_format_csv_unquoted_null_literal_as_null

0

将未加引号的NULL字面量视为\N。

input_format_csv_enum_as_number

0

将CSV格式中插入的枚举值视为枚举索引\N。

input_format_csv_arrays_as_nested_csv

0

从CSV读取数组时,期望其元素以嵌套CSV的形式序列化,然后放入字符串中。例如:"[""Hello"", ""world"", ""42"""" TV""]"。可以省略数组周围的括号。

操作举例

  1. 准备本地文件 test.csv,并写入数据如下。
$ cat /test.csv
    1,2,3
    3,2,1
    78,43,45
  1. ByteHouse 表创建。
    1. 创建 HaMergeTree 表:
create table test.test_local on cluster default_cluster
(
    `column1` UInt32,
    `column2` UInt32,
    `column3` UInt32
)
engine = HaMergeTree('/clickhouse/tables/test/test/{shard}', '{replica}')
order by column1;
  • 创建 Disributed 分布式表:
create table test.test on cluster default
AS test.test
engine = Distributed('default_cluster', 'test', 'test', rand());
  1. 通过 clickhouse-client 向目标表写入数据。
cat data.csv | clickhouse-client --query="INSERT INTO test_local FORMAT CSV"
  1. 查询
select * from test;

注意

常见问题报错: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 值。

从对象存储导入

可直接使用 clickhouse 函数 s3()

INSERT INTO test_local SELECT * from s3(path, [aws_access_key_id, aws_secret_access_key,] [format, [structure, [compression]]])
  • path — Bucket 路径与文件。例如tos-s3-cn-beijing.volces.co``m/test_bucket/test.csv
  • Format — 文件格式,如 CSV。
  • structure — 表格式,填写示例 'column1_name column1_type, column2_name column2_type, ...'
  • compression — 压缩格式,可选,支持 none, gzip/gz, brotli/br, xz/LZMA, zstd/zst

从 HDFS 导入

可直接使用 clickhouse 函数 hdfs()

INSERT INTO test_local SELECT * from hdfs(path, format, structure)
  • path — HDFS 路径与文件。
  • Format — 文件格式,如 CSV。
  • structure — 表格式,填写示例 'column1_name column1_type, column2_name column2_type, ...'