在 ClickHouse 中使用 Native 和二进制格式
ClickHouse 支持多种二进制格式,可以带来更好的性能和空间利用率。二进制格式在字符编码处理方面也更安全,因为数据是以二进制形式保存的。
我们将使用 some_data 表 和 数据 进行演示,可在自己的 ClickHouse 实例上进行复现。
在 ClickHouse 节点之间导出和导入数据时,最高效的数据格式是 Native 格式。导出通过使用 INTO OUTFILE 子句完成:
SELECT * FROM some_data
INTO OUTFILE 'data.clickhouse' FORMAT Native
这将在原生格式下创建 data.clickhouse 文件。
要导入数据,我们可以使用 file() 来处理较小的文件或用于探索性分析:
DESCRIBE file('data.clickhouse', Native);
┌─name──┬─type───┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ path │ String │ │ │ │ │ │
│ month │ Date │ │ │ │ │ │
│ hits │ UInt32 │ │ │ │ │ │
└───────┴────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
提示
在使用 file() 函数并搭配 ClickHouse Cloud 时,需要在文件所在的那台机器上,通过 clickhouse client 运行相关命令。另一种方式是使用 clickhouse-local 在本地查看这些文件。
在生产环境中,我们使用 FROM INFILE 来导入数据:
INSERT INTO sometable
FROM INFILE 'data.clickhouse'
FORMAT Native
在将数据导出为 Native 格式时(以及大多数其他格式),我们也可以通过 COMPRESSION 子句启用压缩:
SELECT * FROM some_data
INTO OUTFILE 'data.clickhouse'
COMPRESSION 'lz4'
FORMAT Native
我们在导出时使用了 LZ4 压缩,因此在导入数据时也需要指定该压缩格式:
INSERT INTO sometable
FROM INFILE 'data.clickhouse'
COMPRESSION 'lz4'
FORMAT Native
导出为 RowBinary
另一种受支持的二进制格式是 RowBinary,它支持以二进制行的形式导入和导出数据:
SELECT * FROM some_data
INTO OUTFILE 'data.binary' FORMAT RowBinary
这将生成一个采用二进制行格式的 data.binary 文件。
探索 RowBinary 文件
此格式不支持自动 schema 推断,因此如果要在加载前进行探索,必须显式定义 schema:
SELECT *
FROM file('data.binary', RowBinary, 'path String, month Date, hits UInt32')
LIMIT 5
┌─路径───────────────────────────┬──────月份─┬─访问次数─┐
│ Bangor_City_Forest │ 2015-07-01 │ 34 │
│ Alireza_Afzal │ 2017-02-01 │ 24 │
│ Akhaura-Laksam-Chittagong_Line │ 2015-09-01 │ 30 │
│ 1973_National_500 │ 2017-10-01 │ 80 │
│ Attachment │ 2017-09-01 │ 1356 │
└────────────────────────────────┴────────────┴──────┘
可以考虑使用 RowBinaryWithNames,它会额外添加一行包含列名的表头。 RowBinaryWithNamesAndTypes 则会再添加一行包含列类型的表头。
从 RowBinary 文件导入
要从 RowBinary 文件加载数据,可以使用 FROM INFILE 子句:
INSERT INTO sometable
FROM INFILE 'data.binary'
FORMAT RowBinary
使用 RawBLOB 导入单个二进制值
假设我们想要读取整个二进制文件,并将其保存到表中的某个字段中。
在这种情况下,可以使用 RawBLOB 格式。此格式只能直接用于仅包含单列的表:
CREATE TABLE images(data String) ENGINE = Memory
我们来将一个图片文件保存到 images 表中:
cat image.jpg | clickhouse-client -q "INSERT INTO images FORMAT RawBLOB"
我们可以检查 data 字段的长度,其值应等于原始文件大小:
SELECT length(data) FROM images
┌─length(data)─┐
│ 6121 │
└──────────────┘
导出 RawBLOB 数据
此格式也可用于配合 INTO OUTFILE 子句导出数据:
SELECT * FROM images LIMIT 1
INTO OUTFILE 'out.jpg'
FORMAT RawBLOB
请注意,我们必须使用 LIMIT 1,否则导出多个值会导致文件损坏。
MessagePack
ClickHouse 支持使用 MsgPack 以 MessagePack 格式进行导入和导出。要导出为 MessagePack 格式:
SELECT *
FROM some_data
INTO OUTFILE 'data.msgpk'
FORMAT MsgPack
要从 MessagePack 文件 导入数据:
INSERT INTO sometable
FROM INFILE 'data.msgpk'
FORMAT MsgPack
Protocol Buffers
Not supported in ClickHouse Cloud
要使用 Protocol Buffers,首先需要定义一个 模式文件(schema 文件):
syntax = "proto3";
message 消息类型 {
string 路径 = 1;
date 月份 = 2;
uint32 访问量 = 3;
};
此模式文件的路径(在本例中为 schema.proto)通过为 Protobuf 格式设置的 format_schema 选项进行配置:
SELECT * FROM some_data
INTO OUTFILE 'proto.bin'
FORMAT Protobuf
SETTINGS format_schema = 'schema:MessageType'
这会将数据保存到 proto.bin 文件中。ClickHouse 还支持导入 Protobuf 数据以及包含嵌套消息的数据。对于处理单个 Protocol Buffer 消息的场景(此时会省略长度分隔符),请考虑使用 ProtobufSingle。
Cap'n Proto
Not supported in ClickHouse Cloud
ClickHouse 支持的另一种流行二进制序列化格式是 Cap'n Proto。与 Protobuf 格式类似,我们也需要在本示例中定义一个 schema 文件(schema.capnp):
@0xec8ff1a10aa10dbe;
struct PathStats {
path @0 :Text;
month @1 :UInt32;
hits @2 :UInt32;
}
现在,我们可以使用 CapnProto 格式和以下模式进行导入和导出:
SELECT
path,
CAST(month, 'UInt32') AS month,
hits
FROM some_data
INTO OUTFILE 'capnp.bin'
FORMAT CapnProto
SETTINGS format_schema = 'schema:PathStats'
请注意,我们需要将 Date 列强制转换为 UInt32 类型,以便与对应的数据类型匹配。
ClickHouse 支持多种格式,包括文本和二进制格式,以满足各种场景和平台的需求。可以在以下文章中了解更多格式以及如何使用它们:
此外,还可以查看 clickhouse-local —— 一款便携的全功能工具,可在不启动 ClickHouse 服务器的情况下处理本地/远程文件。