跳到主要内容

输入和输出数据的格式

ClickHouse 可以接受和返回多种格式的数据。支持的输入格式可以用来解析提供给 INSERT 的数据,从基于文件的表(例如 File、URL 或 HDFS)执行 SELECT,或读取字典。支持的输出格式可以用来排列 SELECT 的结果,以及将数据插入基于文件的表。所有格式名称不区分大小写。

支持的格式为

格式输入输出
TabSeparated
TabSeparatedRaw
TabSeparatedWithNames
TabSeparatedWithNamesAndTypes
TabSeparatedRawWithNames
TabSeparatedRawWithNamesAndTypes
Template
TemplateIgnoreSpaces
CSV
CSVWithNames
CSVWithNamesAndTypes
CustomSeparated
CustomSeparatedWithNames
CustomSeparatedWithNamesAndTypes
SQLInsert
Values
Vertical
JSON
JSONAsString
JSONAsObject
JSONStrings
JSONColumns
JSONColumnsWithMetadata
JSONCompact
JSONCompactStrings
JSONCompactColumns
JSONEachRow
PrettyJSONEachRow
JSONEachRowWithProgress
JSONStringsEachRow
JSONStringsEachRowWithProgress
JSONCompactEachRow
JSONCompactEachRowWithNames
JSONCompactEachRowWithNamesAndTypes
JSONCompactStringsEachRow
JSONCompactStringsEachRowWithNames
JSONCompactStringsEachRowWithNamesAndTypes
JSONObjectEachRow
BSONEachRow
TSKV
Pretty
PrettyNoEscapes
PrettyMonoBlock
PrettyNoEscapesMonoBlock
PrettyCompact
PrettyCompactNoEscapes
PrettyCompactMonoBlock
PrettyCompactNoEscapesMonoBlock
PrettySpace
PrettySpaceNoEscapes
PrettySpaceMonoBlock
PrettySpaceNoEscapesMonoBlock
Prometheus
Protobuf
ProtobufSingle
ProtobufList
Avro
AvroConfluent
Parquet
ParquetMetadata
Arrow
ArrowStream
ORC
One
Npy
RowBinary
RowBinaryWithNames
RowBinaryWithNamesAndTypes
RowBinaryWithDefaults
Native
Null
XML
CapnProto
LineAsString
Regexp
RawBLOB
MsgPack
MySQLDump
DWARF
Markdown
Form

您可以使用 ClickHouse 设置控制某些格式处理参数。有关更多信息,请阅读 设置 部分。

TabSeparated

在 TabSeparated 格式中,数据按行写入。每行包含由制表符分隔的值。每个值后面跟着一个制表符,除了行中的最后一个值,它后面跟着一个换行符。严格来说,所有地方都假设使用 Unix 换行符。最后一行也必须在末尾包含一个换行符。值以文本格式写入,不带引号,特殊字符进行转义。

此格式也可以使用名称 TSV

TabSeparated 格式便于使用自定义程序和脚本处理数据。它在 HTTP 接口和命令行客户端的批处理模式中默认使用。此格式还允许在不同的 DBMS 之间传输数据。例如,您可以从 MySQL 获取转储并将其上传到 ClickHouse,反之亦然。

TabSeparated 格式支持输出总值(在使用 WITH TOTALS 时)和极值(当“extremes”设置为 1 时)。在这种情况下,总值和极值在主数据之后输出。主结果、总值和极值之间用空行分隔。示例

SELECT EventDate, count() AS c FROM test.hits GROUP BY EventDate WITH TOTALS ORDER BY EventDate FORMAT TabSeparated
2014-03-17      1406958
2014-03-18 1383658
2014-03-19 1405797
2014-03-20 1353623
2014-03-21 1245779
2014-03-22 1031592
2014-03-23 1046491

1970-01-01 8873898

2014-03-17 1031592
2014-03-23 1406958

数据格式化

整数以十进制形式写入。数字可以在开头包含额外的“+”字符(解析时忽略,格式化时不记录)。非负数不能包含负号。在读取时,允许将空字符串解析为零,或(对于有符号类型)将仅包含减号的字符串解析为零。不适合相应数据类型的数字可能会被解析为不同的数字,不会出现错误消息。

浮点数以十进制形式写入。点用作小数点分隔符。支持指数项,以及“inf”、“+inf”、“-inf”和“nan”。浮点数项可以以小数点开头或结尾。格式化过程中,浮点数的精度可能会丢失。在解析过程中,不需要严格读取最接近的机器可表示数字。

日期以 YYYY-MM-DD 格式写入,并以相同的格式解析,但可以使用任何字符作为分隔符。带时间的日期以 YYYY-MM-DD hh:mm:ss 格式写入,并以相同的格式解析,但可以使用任何字符作为分隔符。所有这些操作都在客户端或服务器启动时的系统时区中执行(取决于哪个格式化数据)。对于带时间的日期,不指定夏令时。因此,如果转储包含夏令时期间的时间,则该转储不会明确匹配数据,解析将选择两个时间之一。在读取操作期间,不正确的日期和带时间的日期可以使用自然溢出或作为空日期和时间进行解析,不会出现错误消息。

作为例外,如果带时间的日期包含正好 10 个十进制数字,则也支持以 Unix 时间戳格式解析。结果与时区无关。格式 YYYY-MM-DD hh:mm:ssNNNNNNNNNN 可以自动区分。

字符串以反斜杠转义的特殊字符输出。以下转义序列用于输出:\b\f\r\n\t\0\'\\。解析还支持序列 \a\v\xHH(十六进制转义序列)以及任何 \c 序列,其中 c 是任何字符(这些序列将转换为 c)。因此,读取数据支持将换行符写入 \n\,或写入换行符的格式。例如,字符串 Hello world,其单词之间使用换行符而不是空格,可以用以下任何变体进行解析

Hello\nworld

Hello\
world

第二个变体受支持,因为 MySQL 在写入制表符分隔的转储时使用它。

在 TabSeparated 格式中传递数据时,您需要转义的最小字符集是:制表符、换行符 (LF) 和反斜杠。

仅转义一小部分符号。您可能会遇到终端在输出中破坏的字符串值。

数组以方括号中用逗号分隔的值列表的形式写入。数组中的数字项按正常格式化。DateDateTime 类型以单引号括起。字符串以单引号括起,并使用与上述相同的转义规则。

NULL 按设置 format_tsv_null_representation 格式化(默认值为 \N)。

在输入数据中,ENUM 值可以用名称或 ID 表示。首先,我们尝试将输入值与 ENUM 名称匹配。如果我们失败,并且输入值是数字,我们将尝试将此数字与 ENUM ID 匹配。如果输入数据仅包含 ENUM ID,建议启用设置 input_format_tsv_enum_as_number 以优化 ENUM 解析。

嵌套 结构的每个元素都表示为一个数组。

例如

CREATE TABLE nestedt
(
`id` UInt8,
`aux` Nested(
a UInt8,
b String
)
)
ENGINE = TinyLog
INSERT INTO nestedt Values ( 1, [1], ['a'])
SELECT * FROM nestedt FORMAT TSV
1  [1]    ['a']

TabSeparated 格式设置

TabSeparatedRaw

TabSeparated 格式的不同之处在于,行在写入时不会进行转义。使用此格式进行解析时,每个字段中不允许出现制表符或换行符。

此格式也称为 TSVRawRaw

TabSeparatedWithNames

TabSeparated 格式的不同之处在于,列名在第一行写入。

在解析期间,预期第一行包含列名。您可以使用列名来确定它们的位置并检查其正确性。

注意

如果设置 input_format_with_names_use_header 设置为 1,则来自输入数据的列将根据其名称映射到表的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。

此格式也称为 TSVWithNames

TabSeparatedWithNamesAndTypes

TabSeparated 格式的不同之处在于,列名写入第一行,而列类型写入第二行。

注意

如果设置 input_format_with_names_use_header 设置为 1,则来自输入数据的列将根据其名称映射到表的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。如果设置 input_format_with_types_use_header 设置为 1,则将比较来自输入数据的类型与来自表的对应列的类型。否则,将跳过第二行。

此格式也称为 TSVWithNamesAndTypes

TabSeparatedRawWithNames

TabSeparatedWithNames 格式的不同之处在于,行在写入时不会进行转义。使用此格式进行解析时,每个字段中不允许出现制表符或换行符。

此格式也称为 TSVRawWithNamesRawWithNames

TabSeparatedRawWithNamesAndTypes

TabSeparatedWithNamesAndTypes 格式的不同之处在于,行在写入时不会进行转义。使用此格式进行解析时,每个字段中不允许出现制表符或换行符。

此格式也称为 TSVRawWithNamesAndNamesRawWithNamesAndNames

Template

此格式允许使用带有占位符的自定义格式字符串来指定值,并使用指定的转义规则。

它使用设置 format_template_resultsetformat_template_row (format_template_row_format)、format_template_rows_between_delimiter 以及其他格式的一些设置(例如,在使用 JSON 转义时,请参阅 output_format_json_quote_64bit_integers)。

设置 format_template_row 指定包含行格式字符串的文件的路径,格式如下

delimiter_1${column_1:serializeAs_1}delimiter_2${column_2:serializeAs_2} ... delimiter_N,

其中 delimiter_i 是值之间的分隔符($ 符号可以转义为 $$),column_i 是要选择或插入的值的列的名称或索引(如果为空,则跳过该列),serializeAs_i 是列值的转义规则。支持以下转义规则

  • CSVJSONXML(类似于相同名称的格式)
  • Escaped(类似于 TSV
  • Quoted(类似于 Values
  • Raw(无转义,类似于 TSVRaw
  • None(无转义规则,请参阅进一步说明)

如果省略转义规则,则将使用 NoneXML 仅适用于输出。

因此,对于以下格式字符串

  `Search phrase: ${SearchPhrase:Quoted}, count: ${c:Escaped}, ad price: $$${price:JSON};`

将打印(用于选择)或预期(用于插入) SearchPhrasecprice 列的值,这些值分别以 QuotedEscapedJSON 方式转义,分别位于 Search phrase:, count:, ad price: $; 分隔符之间。例如

Search phrase: 'bathroom interior design', count: 2166, ad price: $3;

在将模板格式的格式输出配置部署到集群中所有节点上的目录很困难或不可能,或者格式很简单的情况下,可以使用 format_template_row_format 在查询中直接设置模板字符串,而不是设置包含模板字符串的文件的路径。

format_template_rows_between_delimiter 设置指定行之间的分隔符,该分隔符在除最后一行之外的每一行之后打印(或预期)(默认情况下为 \n)。

设置 format_template_resultset 指定包含结果集格式字符串的文件的路径。设置 format_template_resultset_format 可用于在查询本身中直接设置结果集的模板字符串。结果集的格式字符串与行的格式字符串具有相同的语法,并允许指定前缀、后缀和打印一些附加信息的方式。它包含以下占位符,而不是列名

  • data 是以 format_template_row 格式表示的数据行,以 format_template_rows_between_delimiter 分隔。此占位符必须是格式字符串中的第一个占位符。
  • totals 是以 format_template_row 格式表示的总值行(在使用 WITH TOTALS 时)
  • min 是以 format_template_row 格式表示的最小值行(当极值设置为 1 时)
  • max 是以 format_template_row 格式表示的最大值行(当极值设置为 1 时)
  • rows 是输出行的总数
  • rows_before_limit 是没有 LIMIT 时将存在的最小行数。仅在查询包含 LIMIT 时输出。如果查询包含 GROUP BY,则 rows_before_limit_at_least 是没有 LIMIT 时将存在的精确行数。
  • time 是请求执行时间(以秒为单位)
  • rows_read 是已读取的行数
  • bytes_read 是已读取的字节数(未压缩)

占位符 datatotalsminmax 不得指定转义规则(或显式指定 None)。其余占位符可以指定任何转义规则。如果 format_template_resultset 设置为空字符串,则 ${data} 将用作默认值。对于插入查询,格式允许在某些列或字段中跳过某些列或字段,前提是存在前缀或后缀(请参阅示例)。

选择示例

SELECT SearchPhrase, count() AS c FROM test.hits GROUP BY SearchPhrase ORDER BY c DESC LIMIT 5 FORMAT Template SETTINGS
format_template_resultset = '/some/path/resultset.format', format_template_row = '/some/path/row.format', format_template_rows_between_delimiter = '\n '

/some/path/resultset.format:

<!DOCTYPE HTML>
<html> <head> <title>Search phrases</title> </head>
<body>
<table border="1"> <caption>Search phrases</caption>
<tr> <th>Search phrase</th> <th>Count</th> </tr>
${data}
</table>
<table border="1"> <caption>Max</caption>
${max}
</table>
<b>Processed ${rows_read:XML} rows in ${time:XML} sec</b>
</body>
</html>

/some/path/row.format:

<tr> <td>${0:XML}</td> <td>${1:XML}</td> </tr>

结果

<!DOCTYPE HTML>
<html> <head> <title>Search phrases</title> </head>
<body>
<table border="1"> <caption>Search phrases</caption>
<tr> <th>Search phrase</th> <th>Count</th> </tr>
<tr> <td></td> <td>8267016</td> </tr>
<tr> <td>bathroom interior design</td> <td>2166</td> </tr>
<tr> <td>clickhouse</td> <td>1655</td> </tr>
<tr> <td>spring 2014 fashion</td> <td>1549</td> </tr>
<tr> <td>freeform photos</td> <td>1480</td> </tr>
</table>
<table border="1"> <caption>Max</caption>
<tr> <td></td> <td>8873898</td> </tr>
</table>
<b>Processed 3095973 rows in 0.1569913 sec</b>
</body>
</html>

插入示例

Some header
Page views: 5, User id: 4324182021466249494, Useless field: hello, Duration: 146, Sign: -1
Page views: 6, User id: 4324182021466249494, Useless field: world, Duration: 185, Sign: 1
Total rows: 2
INSERT INTO UserActivity SETTINGS
format_template_resultset = '/some/path/resultset.format', format_template_row = '/some/path/row.format'
FORMAT Template

/some/path/resultset.format:

Some header\n${data}\nTotal rows: ${:CSV}\n

/some/path/row.format:

Page views: ${PageViews:CSV}, User id: ${UserID:CSV}, Useless field: ${:CSV}, Duration: ${Duration:CSV}, Sign: ${Sign:CSV}

PageViewsUserIDDurationSign 占位符中的是表中列的名称。行中的 Useless field 之后以及后缀中的 \nTotal rows: 之后的值将被忽略。输入数据中的所有分隔符必须与指定的格式字符串中的分隔符完全一致。

TemplateIgnoreSpaces

此格式仅适用于输入。与 Template 类似,但在输入流中跳过分隔符和值之间的空格字符。但是,如果格式字符串包含空格字符,则输入流中将预期这些字符。还允许指定空占位符 (${}${:None}) 以将某个分隔符拆分为独立的部分以忽略它们之间的空格。此类占位符仅用于跳过空格字符。如果列的值在所有行中具有相同的顺序,则可以使用此格式读取 JSON。例如,以下请求可用于从格式 JSON 的输出示例中插入数据

INSERT INTO table_name SETTINGS
format_template_resultset = '/some/path/resultset.format', format_template_row = '/some/path/row.format', format_template_rows_between_delimiter = ','
FORMAT TemplateIgnoreSpaces

/some/path/resultset.format:

{${}"meta"${}:${:JSON},${}"data"${}:${}[${data}]${},${}"totals"${}:${:JSON},${}"extremes"${}:${:JSON},${}"rows"${}:${:JSON},${}"rows_before_limit_at_least"${}:${:JSON}${}}

/some/path/row.format:

{${}"SearchPhrase"${}:${}${phrase:JSON}${},${}"c"${}:${}${cnt:JSON}${}}

TSKV

类似于 TabSeparated,但输出以 name=value 格式表示的值。名称以与 TabSeparated 格式相同的方式转义,并且 = 符号也进行了转义。

SearchPhrase=   count()=8267016
SearchPhrase=bathroom interior design count()=2166
SearchPhrase=clickhouse count()=1655
SearchPhrase=2014 spring fashion count()=1549
SearchPhrase=freeform photos count()=1480
SearchPhrase=angelina jolie count()=1245
SearchPhrase=omsk count()=1112
SearchPhrase=photos of dog breeds count()=1091
SearchPhrase=curtain designs count()=1064
SearchPhrase=baku count()=1000

NULL 格式化为 \N

SELECT * FROM t_null FORMAT TSKV
x=1    y=\N

当存在大量小型列时,此格式效率低下,通常没有理由使用它。但是,就效率而言,它并不比 JSONEachRow 差。

此格式支持数据输出和解析。对于解析,支持不同列值的任何顺序。可以省略某些值 - 它们被视为等同于其默认值。在这种情况下,零和空白行用作默认值。无法在表中指定的复杂值不支持作为默认值。

解析允许存在没有等号或值的附加字段 tskv。此字段将被忽略。

在导入期间,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。

CSV

逗号分隔值格式 (RFC).

在格式化时,行用双引号括起来。字符串中的双引号输出为连续的两个双引号。字符转义没有其他规则。日期和日期时间用双引号括起来。数字在没有引号的情况下输出。值用分隔符字符分隔,默认情况下为 ,。分隔符字符在设置 format_csv_delimiter 中定义。行使用 Unix 换行符 (LF) 分隔。数组在 CSV 中序列化如下:首先,数组按 TabSeparated 格式序列化为字符串,然后将结果字符串输出到 CSV 中,并用双引号括起来。CSV 格式中的元组序列化为单独的列(即,它们的嵌套在元组中丢失了)。

$ clickhouse-client --format_csv_delimiter="|" --query="INSERT INTO test.csv FORMAT CSV" < data.csv

*默认情况下,分隔符为 ,。有关更多信息,请参阅 format_csv_delimiter 设置。

在解析时,所有值都可以带引号或不带引号解析。支持双引号和单引号。行也可以不带引号排列。在这种情况下,它们解析到分隔符字符或换行符 (CR 或 LF) 处。违反 RFC,在解析不带引号的行时,将忽略开头和结尾的空格和制表符。对于换行符,支持 Unix (LF)、Windows (CR LF) 和 Mac OS Classic (CR LF) 类型。

NULL 按设置 format_csv_null_representation 格式化(默认值为 \N)。

在输入数据中,枚举值可以表示为名称或 ID。首先,我们尝试将输入值与枚举名称匹配。如果我们失败并且输入值是数字,我们尝试将此数字与枚举 ID 匹配。如果输入数据仅包含枚举 ID,建议启用设置 input_format_csv_enum_as_number 以优化枚举解析。

CSV 格式支持与 `TabSeparated` 相同的方式输出总计和极值。

CSV 格式设置

CSVWithNames

还打印包含列名的标题行,类似于 TabSeparatedWithNames

注意

如果设置 input_format_with_names_use_header 设置为 1,则输入数据中的列将按其名称映射到表中的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。

CSVWithNamesAndTypes

还打印两行标题行,包含列名和类型,类似于 TabSeparatedWithNamesAndTypes

注意

如果设置 input_format_with_names_use_header 设置为 1,则输入数据中的列将按其名称映射到表中的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。如果设置 input_format_with_types_use_header 设置为 1,则将比较输入数据中的类型与表中对应列的类型。否则,将跳过第二行。

CustomSeparated

类似于 Template,但它打印或读取所有列的名称和类型,并使用 format_custom_escaping_rule 设置的转义规则和 format_custom_field_delimiterformat_custom_row_before_delimiterformat_custom_row_after_delimiterformat_custom_row_between_delimiterformat_custom_result_before_delimiterformat_custom_result_after_delimiter 设置中的分隔符,而不是来自格式字符串。

附加设置

还有一个 `CustomSeparatedIgnoreSpaces` 格式,类似于 TemplateIgnoreSpaces

CustomSeparatedWithNames

还打印包含列名的标题行,类似于 TabSeparatedWithNames

注意

如果设置 input_format_with_names_use_header 设置为 1,则输入数据中的列将按其名称映射到表中的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。

CustomSeparatedWithNamesAndTypes

还打印两行标题行,包含列名和类型,类似于 TabSeparatedWithNamesAndTypes

注意

如果设置 input_format_with_names_use_header 设置为 1,则输入数据中的列将按其名称映射到表中的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。如果设置 input_format_with_types_use_header 设置为 1,则将比较输入数据中的类型与表中对应列的类型。否则,将跳过第二行。

SQLInsert

将数据输出为一系列 `INSERT INTO table (columns...) VALUES (...), (...) ...;` 语句。

示例

SELECT number AS x, number + 1 AS y, 'Hello' AS z FROM numbers(10) FORMAT SQLInsert SETTINGS output_format_sql_insert_max_batch_size = 2
INSERT INTO table (x, y, z) VALUES (0, 1, 'Hello'), (1, 2, 'Hello');
INSERT INTO table (x, y, z) VALUES (2, 3, 'Hello'), (3, 4, 'Hello');
INSERT INTO table (x, y, z) VALUES (4, 5, 'Hello'), (5, 6, 'Hello');
INSERT INTO table (x, y, z) VALUES (6, 7, 'Hello'), (7, 8, 'Hello');
INSERT INTO table (x, y, z) VALUES (8, 9, 'Hello'), (9, 10, 'Hello');

要读取此格式输出的数据,可以使用 MySQLDump 输入格式。

SQLInsert 格式设置

JSON

以 JSON 格式输出数据。除了数据表之外,它还输出列名和类型,以及一些附加信息:输出行的总数,以及如果没有限制,可能输出的行数。示例

SELECT SearchPhrase, count() AS c FROM test.hits GROUP BY SearchPhrase WITH TOTALS ORDER BY c DESC LIMIT 5 FORMAT JSON
{
"meta":
[
{
"name": "num",
"type": "Int32"
},
{
"name": "str",
"type": "String"
},
{
"name": "arr",
"type": "Array(UInt8)"
}
],

"data":
[
{
"num": 42,
"str": "hello",
"arr": [0,1]
},
{
"num": 43,
"str": "hello",
"arr": [0,1,2]
},
{
"num": 44,
"str": "hello",
"arr": [0,1,2,3]
}
],

"rows": 3,

"rows_before_limit_at_least": 3,

"statistics":
{
"elapsed": 0.001137687,
"rows_read": 3,
"bytes_read": 24
}
}

该 JSON 与 JavaScript 兼容。为了确保这一点,某些字符会额外转义:斜杠 `\` 会转义为 `\/`;备用换行符 `U+2028` 和 `U+2029` 会破坏一些浏览器,因此会转义为 `\uXXXX`。ASCII 控制字符会转义:退格、换页、换行、回车和水平制表符将替换为 `\b`、`\f`、`\n`、`\r`、`\t`,以及使用 `\uXXXX` 序列的 00-1F 范围内剩余的字节。无效的 UTF-8 序列将更改为替换字符 �,因此输出文本将包含有效的 UTF-8 序列。为了与 JavaScript 兼容,Int64 和 UInt64 整数默认情况下用双引号括起来。要删除引号,可以将配置参数 output_format_json_quote_64bit_integers 设置为 0。

rows - 输出行的总数。

rows_before_limit_at_least 没有 LIMIT 时至少有几行。仅在查询包含 LIMIT 时输出。如果查询包含 GROUP BY,则 rows_before_limit_at_least 是没有 LIMIT 时将有的精确行数。

totals - 总值(使用 WITH TOTALS 时)。

extremes - 极值(将极值设置为 1 时)。

ClickHouse 支持 NULL,它在 JSON 输出中显示为 `null`。要启用输出中的 `+nan`、`-nan`、`+inf`、`-inf` 值,请将 output_format_json_quote_denormals 设置为 1。

另请参阅

对于 JSON 输入格式,如果设置 input_format_json_validate_types_from_metadata 设置为 1,则将比较输入数据中元数据中的类型与表中对应列的类型。

JSONStrings

与 JSON 的区别仅在于数据字段以字符串输出,而不是以类型化的 JSON 值输出。

示例

{
"meta":
[
{
"name": "num",
"type": "Int32"
},
{
"name": "str",
"type": "String"
},
{
"name": "arr",
"type": "Array(UInt8)"
}
],

"data":
[
{
"num": "42",
"str": "hello",
"arr": "[0,1]"
},
{
"num": "43",
"str": "hello",
"arr": "[0,1,2]"
},
{
"num": "44",
"str": "hello",
"arr": "[0,1,2,3]"
}
],

"rows": 3,

"rows_before_limit_at_least": 3,

"statistics":
{
"elapsed": 0.001403233,
"rows_read": 3,
"bytes_read": 24
}
}

JSONColumns

提示

JSONColumns* 格式的输出提供了 ClickHouse 字段名称,然后是该字段的表格的每一行的内容;从视觉上看,数据向左旋转了 90 度。

在此格式中,所有数据都表示为单个 JSON 对象。请注意,JSONColumns 输出格式将所有数据缓冲在内存中,以便将其作为一个块输出,这会导致高内存使用率。

示例

{
"num": [42, 43, 44],
"str": ["hello", "hello", "hello"],
"arr": [[0,1], [0,1,2], [0,1,2,3]]
}

在导入期间,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。块中不存在的列将填充默认值(您可以在此处使用 input_format_defaults_for_omitted_fields 设置)。

JSONColumnsWithMetadata

与 JSONColumns 格式的不同之处在于它还包含一些元数据和统计信息(类似于 JSON 格式)。输出格式将所有数据缓冲在内存中,然后将其作为一个块输出,因此会导致高内存使用率。

示例

{
"meta":
[
{
"name": "num",
"type": "Int32"
},
{
"name": "str",
"type": "String"
},

{
"name": "arr",
"type": "Array(UInt8)"
}
],

"data":
{
"num": [42, 43, 44],
"str": ["hello", "hello", "hello"],
"arr": [[0,1], [0,1,2], [0,1,2,3]]
},

"rows": 3,

"rows_before_limit_at_least": 3,

"statistics":
{
"elapsed": 0.000272376,
"rows_read": 3,
"bytes_read": 24
}
}

对于 JSONColumnsWithMetadata 输入格式,如果设置 input_format_json_validate_types_from_metadata 设置为 1,则将比较输入数据中元数据中的类型与表中对应列的类型。

JSONAsString

在此格式中,单个 JSON 对象被解释为单个值。如果输入包含多个 JSON 对象(逗号分隔),则它们被解释为单独的行。如果输入数据包含在方括号中,则它被解释为 JSON 数组。

此格式只能解析具有单个 字符串 类型字段的表。其余列必须设置为 默认物化,或省略。将整个 JSON 对象收集为字符串后,可以使用 JSON 函数 处理它。

示例

查询

DROP TABLE IF EXISTS json_as_string;
CREATE TABLE json_as_string (json String) ENGINE = Memory;
INSERT INTO json_as_string (json) FORMAT JSONAsString {"foo":{"bar":{"x":"y"},"baz":1}},{},{"any json stucture":1}
SELECT * FROM json_as_string;

结果

┌─json──────────────────────────────┐
│ {"foo":{"bar":{"x":"y"},"baz":1}} │
│ {} │
│ {"any json stucture":1} │
└───────────────────────────────────┘

JSON 对象数组

查询

CREATE TABLE json_square_brackets (field String) ENGINE = Memory;
INSERT INTO json_square_brackets FORMAT JSONAsString [{"id": 1, "name": "name1"}, {"id": 2, "name": "name2"}];

SELECT * FROM json_square_brackets;

结果

┌─field──────────────────────┐
│ {"id": 1, "name": "name1"} │
│ {"id": 2, "name": "name2"} │
└────────────────────────────┘

JSONAsObject

在此格式中,单个 JSON 对象被解释为单个 JSON 值。如果输入包含多个 JSON 对象(逗号分隔),则它们被解释为单独的行。如果输入数据包含在方括号中,则它被解释为 JSON 数组。

此格式只能解析具有单个 JSON 类型字段的表。其余列必须设置为 默认物化

示例

查询

SET allow_experimental_json_type = 1;
CREATE TABLE json_as_object (json JSON) ENGINE = Memory;
INSERT INTO json_as_object (json) FORMAT JSONAsObject {"foo":{"bar":{"x":"y"},"baz":1}},{},{"any json stucture":1}
SELECT * FROM json_as_object FORMAT JSONEachRow;

结果

{"json":{"foo":{"bar":{"x":"y"},"baz":"1"}}}
{"json":{}}
{"json":{"any json stucture":"1"}}

JSON 对象数组

查询

SET allow_experimental_json_type = 1;
CREATE TABLE json_square_brackets (field JSON) ENGINE = Memory;
INSERT INTO json_square_brackets FORMAT JSONAsObject [{"id": 1, "name": "name1"}, {"id": 2, "name": "name2"}];
SELECT * FROM json_square_brackets FORMAT JSONEachRow;

结果

{"field":{"id":"1","name":"name1"}}
{"field":{"id":"2","name":"name2"}}

具有默认值的列

SET allow_experimental_json_type = 1;
CREATE TABLE json_as_object (json JSON, time DateTime MATERIALIZED now()) ENGINE = Memory;
INSERT INTO json_as_object (json) FORMAT JSONAsObject {"foo":{"bar":{"x":"y"},"baz":1}};
INSERT INTO json_as_object (json) FORMAT JSONAsObject {};
INSERT INTO json_as_object (json) FORMAT JSONAsObject {"any json stucture":1}
SELECT time, json FROM json_as_object FORMAT JSONEachRow
{"time":"2024-09-16 12:18:10","json":{}}
{"time":"2024-09-16 12:18:13","json":{"any json stucture":"1"}}
{"time":"2024-09-16 12:18:08","json":{"foo":{"bar":{"x":"y"},"baz":"1"}}}

JSONCompact

与 JSON 的区别仅在于数据行输出在数组中,而不是在对象中。

示例

{
"meta":
[
{
"name": "num",
"type": "Int32"
},
{
"name": "str",
"type": "String"
},
{
"name": "arr",
"type": "Array(UInt8)"
}
],

"data":
[
[42, "hello", [0,1]],
[43, "hello", [0,1,2]],
[44, "hello", [0,1,2,3]]
],

"rows": 3,

"rows_before_limit_at_least": 3,

"statistics":
{
"elapsed": 0.001222069,
"rows_read": 3,
"bytes_read": 24
}
}

JSONCompactStrings

与 JSONStrings 的区别仅在于数据行输出在数组中,而不是在对象中。

示例:f

{
"meta":
[
{
"name": "num",
"type": "Int32"
},
{
"name": "str",
"type": "String"
},
{
"name": "arr",
"type": "Array(UInt8)"
}
],

"data":
[
["42", "hello", "[0,1]"],
["43", "hello", "[0,1,2]"],
["44", "hello", "[0,1,2,3]"]
],

"rows": 3,

"rows_before_limit_at_least": 3,

"statistics":
{
"elapsed": 0.001572097,
"rows_read": 3,
"bytes_read": 24
}
}

JSONCompactColumns

在此格式中,所有数据都表示为单个 JSON 数组。请注意,JSONCompactColumns 输出格式会将所有数据缓冲在内存中以将其作为单个块输出,这会导致高内存消耗。

示例

[
[42, 43, 44],
["hello", "hello", "hello"],
[[0,1], [0,1,2], [0,1,2,3]]
]

块中不存在的列将使用默认值填充(您可以使用 input_format_defaults_for_omitted_fields 设置)。

JSONEachRow

在此格式中,ClickHouse 将每行输出为一个分隔的、换行符分隔的 JSON 对象。

示例

{"num":42,"str":"hello","arr":[0,1]}
{"num":43,"str":"hello","arr":[0,1,2]}
{"num":44,"str":"hello","arr":[0,1,2,3]}

在导入数据时,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过名称未知的列。

PrettyJSONEachRow

与 JSONEachRow 的区别仅在于 JSON 使用换行符分隔符和 4 个空格缩进进行了格式化。仅适用于输出。

示例

{
"num": "42",
"str": "hello",
"arr": [
"0",
"1"
],
"tuple": {
"num": 42,
"str": "world"
}
}
{
"num": "43",
"str": "hello",
"arr": [
"0",
"1",
"2"
],
"tuple": {
"num": 43,
"str": "world"
}
}

JSONStringsEachRow

与 JSONEachRow 的区别仅在于数据字段输出为字符串,而不是类型化的 JSON 值。

示例

{"num":"42","str":"hello","arr":"[0,1]"}
{"num":"43","str":"hello","arr":"[0,1,2]"}
{"num":"44","str":"hello","arr":"[0,1,2,3]"}

JSONCompactEachRow

与 JSONEachRow 的区别仅在于数据行输出在数组中,而不是在对象中。

示例

[42, "hello", [0,1]]
[43, "hello", [0,1,2]]
[44, "hello", [0,1,2,3]]

JSONCompactStringsEachRow

与 JSONCompactEachRow 的区别仅在于数据字段输出为字符串,而不是类型化的 JSON 值。

示例

["42", "hello", "[0,1]"]
["43", "hello", "[0,1,2]"]
["44", "hello", "[0,1,2,3]"]

JSONEachRowWithProgress

JSONStringsEachRowWithProgress

JSONEachRow/JSONStringsEachRow 的区别在于 ClickHouse 还会以 JSON 值的形式产生进度信息。

{"row":{"num":42,"str":"hello","arr":[0,1]}}
{"row":{"num":43,"str":"hello","arr":[0,1,2]}}
{"row":{"num":44,"str":"hello","arr":[0,1,2,3]}}
{"progress":{"read_rows":"3","read_bytes":"24","written_rows":"0","written_bytes":"0","total_rows_to_read":"3"}}

JSONCompactEachRowWithNames

JSONCompactEachRow 格式的区别在于它还会打印包含列名的标题行,类似于 TabSeparatedWithNames

注意

如果设置 input_format_with_names_use_header 设置为 1,则输入数据中的列将按其名称映射到表中的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。

JSONCompactEachRowWithNamesAndTypes

JSONCompactEachRow 格式的区别在于它还会打印包含列名和类型的两个标题行,类似于 TabSeparatedWithNamesAndTypes

注意

如果设置 input_format_with_names_use_header 设置为 1,则输入数据中的列将按其名称映射到表中的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。如果设置 input_format_with_types_use_header 设置为 1,则将比较输入数据中的类型与表中对应列的类型。否则,将跳过第二行。

JSONCompactStringsEachRowWithNames

JSONCompactStringsEachRow 的区别在于它还会打印包含列名的标题行,类似于 TabSeparatedWithNames

注意

如果设置 input_format_with_names_use_header 设置为 1,则输入数据中的列将按其名称映射到表中的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。

JSONCompactStringsEachRowWithNamesAndTypes

JSONCompactStringsEachRow 的区别在于它还会打印包含列名和类型的两个标题行,类似于 TabSeparatedWithNamesAndTypes

注意

如果设置 input_format_with_names_use_header 设置为 1,则输入数据中的列将按其名称映射到表中的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。如果设置 input_format_with_types_use_header 设置为 1,则将比较输入数据中的类型与表中对应列的类型。否则,将跳过第二行。

["num", "str", "arr"]
["Int32", "String", "Array(UInt8)"]
[42, "hello", [0,1]]
[43, "hello", [0,1,2]]
[44, "hello", [0,1,2,3]]

JSONObjectEachRow

在此格式中,所有数据都表示为单个 JSON 对象,每行表示为该对象的单独字段,类似于 JSONEachRow 格式。

示例

{
"row_1": {"num": 42, "str": "hello", "arr": [0,1]},
"row_2": {"num": 43, "str": "hello", "arr": [0,1,2]},
"row_3": {"num": 44, "str": "hello", "arr": [0,1,2,3]}
}

要使用对象名称作为列值,可以使用特殊设置 format_json_object_each_row_column_for_object_name。此设置的值设置为用作结果对象中行 JSON 键的列的名称。示例

用于输出

假设我们有一个包含两列的表 test

┌─object_name─┬─number─┐
│ first_obj │ 1 │
│ second_obj │ 2 │
│ third_obj │ 3 │
└─────────────┴────────┘

让我们以 JSONObjectEachRow 格式输出它,并使用 format_json_object_each_row_column_for_object_name 设置

select * from test settings format_json_object_each_row_column_for_object_name='object_name'

输出

{
"first_obj": {"number": 1},
"second_obj": {"number": 2},
"third_obj": {"number": 3}
}

用于输入

假设我们将上一个示例的输出存储在一个名为 data.json 的文件中

select * from file('data.json', JSONObjectEachRow, 'object_name String, number UInt64') settings format_json_object_each_row_column_for_object_name='object_name'
┌─object_name─┬─number─┐
│ first_obj │ 1 │
│ second_obj │ 2 │
│ third_obj │ 3 │
└─────────────┴────────┘

它在模式推断中也有效

desc file('data.json', JSONObjectEachRow) settings format_json_object_each_row_column_for_object_name='object_name'
┌─name────────┬─type────────────┐
│ object_name │ String │
│ number │ Nullable(Int64) │
└─────────────┴─────────────────┘

插入数据

INSERT INTO UserActivity FORMAT JSONEachRow {"PageViews":5, "UserID":"4324182021466249494", "Duration":146,"Sign":-1} {"UserID":"4324182021466249494","PageViews":6,"Duration":185,"Sign":1}

ClickHouse 允许

  • 对象中键值对的任何顺序。
  • 省略某些值。

ClickHouse 忽略元素和对象后面的逗号之间的空格。您可以在一行中传递所有对象。您不必用换行符将它们分开。

省略值处理

ClickHouse 将省略的值替换为相应 数据类型 的默认值。

如果指定了 DEFAULT expr,ClickHouse 会根据 input_format_defaults_for_omitted_fields 设置使用不同的替换规则。

考虑以下表

CREATE TABLE IF NOT EXISTS example_table
(
x UInt32,
a DEFAULT x * 2
) ENGINE = Memory;
  • 如果 input_format_defaults_for_omitted_fields = 0,则 xa 的默认值等于 0(作为 UInt32 数据类型的默认值)。
  • 如果 input_format_defaults_for_omitted_fields = 1,则 x 的默认值等于 0,但 a 的默认值等于 x * 2
注意

在使用 input_format_defaults_for_omitted_fields = 1 插入数据时,与使用 input_format_defaults_for_omitted_fields = 0 插入数据相比,ClickHouse 会消耗更多计算资源。

选择数据

UserActivity 表为例

┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ -1 │
│ 4324182021466249494 │ 6 │ 185 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘

查询 SELECT * FROM UserActivity FORMAT JSONEachRow 返回

{"UserID":"4324182021466249494","PageViews":5,"Duration":146,"Sign":-1}
{"UserID":"4324182021466249494","PageViews":6,"Duration":185,"Sign":1}

JSON 格式不同,不会替换无效的 UTF-8 序列。值以与 JSON 相同的方式进行转义。

信息

任何字节集都可以输出到字符串中。如果您确定表中的数据可以在不丢失任何信息的情况下格式化为 JSON,请使用 JSONEachRow 格式。

嵌套结构的使用

如果您有一个包含 嵌套 数据类型列的表,您可以插入具有相同结构的 JSON 数据。使用 input_format_import_nested_json 设置启用此功能。

例如,考虑以下表

CREATE TABLE json_each_row_nested (n Nested (s String, i Int32) ) ENGINE = Memory

如您在 Nested 数据类型描述中所见,ClickHouse 将嵌套结构的每个组件都视为单独的列(对于我们的表,为 n.sn.i)。您可以通过以下方式插入数据

INSERT INTO json_each_row_nested FORMAT JSONEachRow {"n.s": ["abc", "def"], "n.i": [1, 23]}

要将数据插入为分层 JSON 对象,请设置 input_format_import_nested_json=1

{
"n": {
"s": ["abc", "def"],
"i": [1, 23]
}
}

没有此设置,ClickHouse 会抛出异常。

SELECT name, value FROM system.settings WHERE name = 'input_format_import_nested_json'
┌─name────────────────────────────┬─value─┐
│ input_format_import_nested_json │ 0 │
└─────────────────────────────────┴───────┘
INSERT INTO json_each_row_nested FORMAT JSONEachRow {"n": {"s": ["abc", "def"], "i": [1, 23]}}
Code: 117. DB::Exception: Unknown field found while parsing JSONEachRow format: n: (at row 1)
SET input_format_import_nested_json=1
INSERT INTO json_each_row_nested FORMAT JSONEachRow {"n": {"s": ["abc", "def"], "i": [1, 23]}}
SELECT * FROM json_each_row_nested
┌─n.s───────────┬─n.i────┐
│ ['abc','def'] │ [1,23] │
└───────────────┴────────┘

JSON 格式设置

BSONEachRow

在此格式中,ClickHouse 以 BSON 文档序列的形式格式化/解析数据,文档之间没有任何分隔符。每行都格式化为单个文档,每列都格式化为单个 BSON 文档字段,其列名作为键。

对于输出,它使用 ClickHouse 类型和 BSON 类型之间的以下对应关系

ClickHouse 类型BSON 类型
Bool\x08 boolean
Int8/UInt8/Enum8\x10 int32
Int16/UInt16/Enum16\x10 int32
Int32\x10 int32
UInt32\x12 int64
Int64/UInt64\x12 int64
Float32/Float64\x01 double
Date/Date32\x10 int32
DateTime\x12 int64
DateTime64\x09 datetime
Decimal32\x10 int32
Decimal64\x12 int64
Decimal128\x05 binary, \x00 binary subtype, size = 16
Decimal256\x05 binary, \x00 binary subtype, size = 32
Int128/UInt128\x05 binary, \x00 binary subtype, size = 16
Int256/UInt256\x05 binary, \x00 binary subtype, size = 32
String/FixedString\x05 binary, \x00 binary subtype 或 \x02 string(如果设置 output_format_bson_string_as_string 启用)
UUID\x05 binary, \x04 uuid subtype, size = 16
Array\x04 array
Tuple\x04 array
Named Tuple\x03 document
Map\x03 document
IPv4\x10 int32
IPv6\x05 binary, \x00 binary subtype

对于输入,它使用 BSON 类型和 ClickHouse 类型之间的以下对应关系

BSON 类型ClickHouse 类型
\x01 doubleFloat32/Float64
\x02 stringString/FixedString
\x03 documentMap/Named Tuple
\x04 arrayArray/Tuple
\x05 binary, \x00 binary subtypeString/FixedString/IPv6
\x05 binary, \x02 old binary subtypeString/FixedString
\x05 binary, \x03 old uuid subtypeUUID
\x05 binary, \x04 uuid subtypeUUID
\x07 ObjectIdString/FixedString
\x08 booleanBool
\x09 datetimeDateTime64
\x0A null valueNULL
\x0D JavaScript codeString/FixedString
\x0E symbolString/FixedString
\x10 int32Int32/UInt32/Decimal32/IPv4/Enum8/Enum16
\x12 int64Int64/UInt64/Decimal64/DateTime64

不支持其他 BSON 类型。此外,它还执行不同整数类型之间的转换(例如,您可以将 BSON int32 值插入 ClickHouse UInt8)。大整数和小数(Int128/UInt128/Int256/UInt256/Decimal128/Decimal256)可以从 BSON Binary 值(带有 \x00 二进制子类型)解析。在这种情况下,此格式将验证二进制数据的 size 是否等于预期值的 size。

注意:此格式在大端平台上不能正常工作。

BSON 格式设置

Native

最有效的格式。数据以二进制格式按块写入和读取。对于每个块,会依次记录行数、列数、列名和类型以及该块中的列部分。换句话说,此格式是“列式”的——它不会将列转换为行。这是服务器之间交互、使用命令行客户端以及 C++ 客户端使用的格式。

您可以使用此格式快速生成仅 ClickHouse DBMS 可读取的转储。自己使用此格式没有意义。

Null

不输出任何内容。但是,查询会得到处理,并且在使用命令行客户端时,数据会传输到客户端。这用于测试,包括性能测试。显然,此格式仅适用于输出,不适用于解析。

Pretty

将数据输出为 Unicode-art 表格,还使用 ANSI 转义序列在终端设置颜色。会绘制表格的完整网格,每行在终端占据两行。每个结果块都输出为一个单独的表格。这对于能够在不缓冲结果的情况下输出块是必要的(为了预先计算所有值的可见宽度,需要缓冲结果)。

NULL 输出为 ᴺᵁᴸᴸ

示例(针对 PrettyCompact 格式显示)

SELECT * FROM t_null
┌─x─┬────y─┐
│ 1 │ ᴺᵁᴸᴸ │
└───┴──────┘

Pretty 格式中的行不会转义*格式。示例针对 PrettyCompact 格式显示

SELECT 'String with \'quotes\' and \t character' AS Escaping_test
┌─Escaping_test────────────────────────┐
│ String with 'quotes' and character │
└──────────────────────────────────────┘

为了避免向终端转储太多数据,只打印前 10,000 行。如果行数大于或等于 10,000,则会打印消息“显示了前 10,000 行”。此格式仅适用于输出查询结果,不适用于解析(检索数据以插入表格)。

Pretty 格式支持输出总计值(使用 WITH TOTALS 时)和极值(当“extremes”设置为 1 时)。在这些情况下,总计值和极值会输出在主数据之后,位于单独的表格中。示例(针对 PrettyCompact 格式显示)

SELECT EventDate, count() AS c FROM test.hits GROUP BY EventDate WITH TOTALS ORDER BY EventDate FORMAT PrettyCompact
┌──EventDate─┬───────c─┐
│ 2014-03-17 │ 1406958 │
│ 2014-03-18 │ 1383658 │
│ 2014-03-19 │ 1405797 │
│ 2014-03-20 │ 1353623 │
│ 2014-03-21 │ 1245779 │
│ 2014-03-22 │ 1031592 │
│ 2014-03-23 │ 1046491 │
└────────────┴─────────┘

Totals:
┌──EventDate─┬───────c─┐
│ 1970-01-01 │ 8873898 │
└────────────┴─────────┘

Extremes:
┌──EventDate─┬───────c─┐
│ 2014-03-17 │ 1031592 │
│ 2014-03-23 │ 1406958 │
└────────────┴─────────┘

PrettyNoEscapes

Pretty 不同,它不使用 ANSI 转义序列。这是为了在浏览器中显示此格式以及使用“watch”命令行实用程序而必需的。

示例

$ watch -n1 "clickhouse-client --query='SELECT event, value FROM system.events FORMAT PrettyCompactNoEscapes'"

您可以使用 HTTP 接口在浏览器中显示。

PrettyMonoBlock

Pretty 不同,它最多会缓冲 10,000 行,然后以单个表格形式输出,而不是按块输出。

PrettyNoEscapesMonoBlock

PrettyNoEscapes 不同,它最多会缓冲 10,000 行,然后以单个表格形式输出,而不是按块输出。

PrettyCompact

Pretty 不同,它在行之间绘制网格,结果更加紧凑。此格式默认在命令行客户端的交互模式中使用。

PrettyCompactNoEscapes

PrettyCompact 不同,它不使用 ANSI 转义序列。这是为了在浏览器中显示此格式以及使用“watch”命令行实用程序而必需的。

PrettyCompactMonoBlock

PrettyCompact 不同,它最多会缓冲 10,000 行,然后以单个表格形式输出,而不是按块输出。

PrettyCompactNoEscapesMonoBlock

PrettyCompactNoEscapes 不同,它最多会缓冲 10,000 行,然后以单个表格形式输出,而不是按块输出。

PrettySpace

PrettyCompact 不同,它使用空格(空格字符)而不是网格。

PrettySpaceNoEscapes

PrettySpace 不同,它不使用 ANSI 转义序列。这是为了在浏览器中显示此格式以及使用“watch”命令行实用程序而必需的。

PrettySpaceMonoBlock

PrettySpace 不同,它最多会缓冲 10,000 行,然后以单个表格形式输出,而不是按块输出。

PrettySpaceNoEscapesMonoBlock

PrettySpaceNoEscapes 不同,它最多会缓冲 10,000 行,然后以单个表格形式输出,而不是按块输出。

Pretty 格式设置

RowBinary

按行以二进制格式格式化和解析数据。行和值连续列出,没有分隔符。由于数据采用二进制格式,因此 FORMAT RowBinary 之后的定界符严格指定为下一个:任何数量的空格(' ' - 空格,代码 0x20'\t' - 制表符,代码 0x09'\f' - 换页符,代码 0x0C)后面紧跟一个换行符序列(Windows 样式 "\r\n" 或 Unix 样式 '\n'),紧跟二进制数据。这种格式不如 Native 格式高效,因为它基于行。

整数使用固定长度的小端表示。例如,UInt64 使用 8 个字节。DateTime 表示为包含 Unix 时间戳作为值的 UInt32。Date 表示为包含自 1970-01-01 以来的天数作为值的 UInt16 对象。String 表示为 varint 长度(无符号 LEB128),后面跟着字符串的字节。FixedString 表示为简单的字节序列。

数组表示为 varint 长度(无符号 LEB128),后面跟着数组的连续元素。

对于 NULL 支持,在每个 Nullable 值之前添加一个包含 1 或 0 的额外字节。如果是 1,则该值为 NULL,并且此字节被解释为一个单独的值。如果是 0,则字节后的值不是 NULL

RowBinaryWithNames

类似于 RowBinary,但添加了标题

  • LEB128-encoded number of columns (N)
  • N 个 String 指定列名
注意

如果设置 input_format_with_names_use_header 设置为 1,则输入数据中的列将按其名称映射到表中的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。

RowBinaryWithNamesAndTypes

类似于 RowBinary,但添加了标题

  • LEB128-encoded number of columns (N)
  • N 个 String 指定列名
  • N 个 String 指定列类型
注意

如果设置 input_format_with_names_use_header 设置为 1,则输入数据中的列将按其名称映射到表中的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。否则,将跳过第一行。如果设置 input_format_with_types_use_header 设置为 1,则将比较输入数据中的类型与表中对应列的类型。否则,将跳过第二行。

RowBinaryWithDefaults

类似于 RowBinary,但在每列之前都添加一个额外字节,以指示是否应该使用默认值。

示例

:) select * from format('RowBinaryWithDefaults', 'x UInt32 default 42, y UInt32', x'010001000000')

┌──x─┬─y─┐
421
└────┴───┘

对于列 x,只有一个字节 01 指示应使用默认值,并且此字节之后没有提供其他数据。对于列 y,数据以字节 00 开头,表示该列具有应从后续数据 01000000 中读取的实际值。

RowBinary 格式设置

Values

打印每行在括号中。行用逗号分隔。最后一行后面没有逗号。括号内的值也是用逗号分隔的。数字以十进制格式输出,没有引号。数组在方括号中输出。字符串、日期和带时间的日期在引号中输出。转义规则和解析类似于 TabSeparated 格式。在格式化期间,不会插入额外的空格,但在解析期间,允许并跳过它们(数组值内的空格除外,不允许)。 NULL 表示为 NULL

在 Values ​​格式中传递数据时,您需要转义的最小字符集:单引号和反斜杠。

这是在 INSERT INTO t VALUES ... 中使用的格式,但您也可以将其用于格式化查询结果。

Values 格式设置

Vertical

在单独的行上打印每个值,并指定列名。如果每行包含大量列,则这种格式便于打印只有一行或几行。

NULL 输出为 ᴺᵁᴸᴸ

示例

SELECT * FROM t_null FORMAT Vertical
Row 1:
──────
x: 1
y: ᴺᵁᴸᴸ

Vertical 格式中不会转义行

SELECT 'string with \'quotes\' and \t with some special \n characters' AS test FORMAT Vertical
Row 1:
──────
test: string with 'quotes' and with some special
characters

此格式仅适合输出查询结果,而不适合解析(检索要插入表中的数据)。

XML

XML 格式仅适合输出,不适合解析。例子

<?xml version='1.0' encoding='UTF-8' ?>
<result>
<meta>
<columns>
<column>
<name>SearchPhrase</name>
<type>String</type>
</column>
<column>
<name>count()</name>
<type>UInt64</type>
</column>
</columns>
</meta>
<data>
<row>
<SearchPhrase></SearchPhrase>
<field>8267016</field>
</row>
<row>
<SearchPhrase>bathroom interior design</SearchPhrase>
<field>2166</field>
</row>
<row>
<SearchPhrase>clickhouse</SearchPhrase>
<field>1655</field>
</row>
<row>
<SearchPhrase>2014 spring fashion</SearchPhrase>
<field>1549</field>
</row>
<row>
<SearchPhrase>freeform photos</SearchPhrase>
<field>1480</field>
</row>
<row>
<SearchPhrase>angelina jolie</SearchPhrase>
<field>1245</field>
</row>
<row>
<SearchPhrase>omsk</SearchPhrase>
<field>1112</field>
</row>
<row>
<SearchPhrase>photos of dog breeds</SearchPhrase>
<field>1091</field>
</row>
<row>
<SearchPhrase>curtain designs</SearchPhrase>
<field>1064</field>
</row>
<row>
<SearchPhrase>baku</SearchPhrase>
<field>1000</field>
</row>
</data>
<rows>10</rows>
<rows_before_limit_at_least>141137</rows_before_limit_at_least>
</result>

如果列名没有可接受的格式,则仅使用“field”作为元素名称。通常,XML 结构遵循 JSON 结构。与 JSON 一样,无效的 UTF-8 序列将更改为替换字符 �,因此输出文本将包含有效的 UTF-8 序列。

在字符串值中,<& 字符将分别转义为 <&

数组输出为 <array><elem>Hello</elem><elem>World</elem>...</array>,元组输出为 <tuple><elem>Hello</elem><elem>World</elem>...</tuple>

CapnProto

CapnProto 是一种二进制消息格式,类似于 Protocol BuffersThrift,但不类似于 JSONMessagePack.

CapnProto 消息是严格类型的,不是自描述的,这意味着它们需要外部模式描述。模式是在运行时应用的,并为每个查询缓存。

另请参阅 格式模式.

数据类型匹配

下表显示了支持的数据类型以及它们在 INSERTSELECT 查询中与 ClickHouse 数据类型 的匹配方式。

CapnProto 数据类型 (INSERT)ClickHouse 数据类型CapnProto 数据类型 (SELECT)
UINT8, BOOLUInt8UINT8
INT8Int8INT8
UINT16UInt16, DateUINT16
INT16Int16INT16
UINT32UInt32, DateTimeUINT32
INT32Int32, Decimal32INT32
UINT64UInt64UINT64
INT64Int64, DateTime64, Decimal64INT64
FLOAT32Float32FLOAT32
FLOAT64Float64FLOAT64
TEXT, DATAString, FixedStringTEXT, DATA
union(T, Void), union(Void, T)Nullable(T)union(T, Void), union(Void, T)
ENUMEnum(8/16)ENUM
LISTArrayLIST
STRUCTTupleSTRUCT
UINT32IPv4UINT32
DATAIPv6DATA
DATAInt128/UInt128/Int256/UInt256DATA
DATADecimal128/Decimal256DATA
STRUCT(entries LIST(STRUCT(key Key, value Value)))MapSTRUCT(entries LIST(STRUCT(key Key, value Value)))

整数类型可以在输入/输出期间相互转换。

要使用 CapnProto 格式处理 Enum,请使用 format_capn_proto_enum_comparising_mode 设置。

数组可以嵌套,并且可以将 Nullable 类型的值作为参数。TupleMap 类型也可以嵌套。

插入和选择数据

您可以使用以下命令将 CapnProto 数据从文件插入 ClickHouse 表中

$ cat capnproto_messages.bin | clickhouse-client --query "INSERT INTO test.hits SETTINGS format_schema = 'schema:Message' FORMAT CapnProto"

其中 schema.capnp 如下所示

struct Message {
SearchPhrase @0 :Text;
c @1 :Uint64;
}

您可以从 ClickHouse 表中选择数据,并使用以下命令将它们保存到 CapnProto 格式的某个文件中

$ clickhouse-client --query = "SELECT * FROM test.hits FORMAT CapnProto SETTINGS format_schema = 'schema:Message'"

使用自动生成的模式

如果您没有数据的外部 CapnProto 模式,您仍然可以使用自动生成的模式以 CapnProto 格式输出/输入数据。例如

SELECT * FROM test.hits format CapnProto SETTINGS format_capn_proto_use_autogenerated_schema=1

在这种情况下,ClickHouse 将根据表结构使用函数 structureToCapnProtoSchema 自动生成 CapnProto 模式,并将使用此模式以 CapnProto 格式序列化数据。

您还可以使用自动生成的模式读取 CapnProto 文件(在这种情况下,文件必须使用相同的模式创建)

$ cat hits.bin | clickhouse-client --query "INSERT INTO test.hits SETTINGS format_capn_proto_use_autogenerated_schema=1 FORMAT CapnProto"

设置 format_capn_proto_use_autogenerated_schema 默认情况下处于启用状态,如果 format_schema 未设置,则适用。

您还可以使用设置 output_format_schema 在输入/输出期间将自动生成的模式保存在文件中。例如

SELECT * FROM test.hits format CapnProto SETTINGS format_capn_proto_use_autogenerated_schema=1, output_format_schema='path/to/schema/schema.capnp'

在这种情况下,自动生成的 CapnProto 模式将保存在文件 path/to/schema/schema.capnp 中。

Prometheus

Prometheus 基于文本的公开格式 公开指标。

输出表应具有正确的结构。name (String) 和 value(数字)列是必需的。行可以选择包含 help (String) 和 timestamp(数字)。type (String) 列是 countergaugehistogramsummaryuntyped 或空。每个指标值也可能有一些 labels (Map(String, String))。几个连续的行可以引用具有不同标签的同一个指标。表应按指标名称排序(例如,使用 ORDER BY name)。

histogramsummary 的标签有特殊要求,详情请参考 Prometheus 文档。带有标签 {'count':''}{'sum':''} 的行将分别转换为 <metric_name>_count<metric_name>_sum

示例

┌─name────────────────────────────────┬─type──────┬─help──────────────────────────────────────┬─labels─────────────────────────┬────value─┬─────timestamp─┐
│ http_request_duration_seconds │ histogram │ A histogram of the request duration. │ {'le':'0.05'} │ 24054 │ 0 │
│ http_request_duration_seconds │ histogram │ │ {'le':'0.1'} │ 33444 │ 0 │
│ http_request_duration_seconds │ histogram │ │ {'le':'0.2'} │ 100392 │ 0 │
│ http_request_duration_seconds │ histogram │ │ {'le':'0.5'} │ 129389 │ 0 │
│ http_request_duration_seconds │ histogram │ │ {'le':'1'} │ 133988 │ 0 │
│ http_request_duration_seconds │ histogram │ │ {'le':'+Inf'} │ 144320 │ 0 │
│ http_request_duration_seconds │ histogram │ │ {'sum':''} │ 53423 │ 0 │
│ http_requests_total │ counter │ Total number of HTTP requests │ {'method':'post','code':'200'} │ 1027 │ 1395066363000 │
│ http_requests_total │ counter │ │ {'method':'post','code':'400'} │ 3 │ 1395066363000 │
│ metric_without_timestamp_and_labels │ │ │ {} │ 12.47 │ 0 │
│ rpc_duration_seconds │ summary │ A summary of the RPC duration in seconds. │ {'quantile':'0.01'} │ 3102 │ 0 │
│ rpc_duration_seconds │ summary │ │ {'quantile':'0.05'} │ 3272 │ 0 │
│ rpc_duration_seconds │ summary │ │ {'quantile':'0.5'} │ 4773 │ 0 │
│ rpc_duration_seconds │ summary │ │ {'quantile':'0.9'} │ 9001 │ 0 │
│ rpc_duration_seconds │ summary │ │ {'quantile':'0.99'} │ 76656 │ 0 │
│ rpc_duration_seconds │ summary │ │ {'count':''} │ 2693 │ 0 │
│ rpc_duration_seconds │ summary │ │ {'sum':''} │ 17560473 │ 0 │
│ something_weird │ │ │ {'problem':'division by zero'} │ inf │ -3982045 │
└─────────────────────────────────────┴───────────┴───────────────────────────────────────────┴────────────────────────────────┴──────────┴───────────────┘

格式为

# HELP http_request_duration_seconds A histogram of the request duration.
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.05"} 24054
http_request_duration_seconds_bucket{le="0.1"} 33444
http_request_duration_seconds_bucket{le="0.5"} 129389
http_request_duration_seconds_bucket{le="1"} 133988
http_request_duration_seconds_bucket{le="+Inf"} 144320
http_request_duration_seconds_sum 53423
http_request_duration_seconds_count 144320

# HELP http_requests_total Total number of HTTP requests
# TYPE http_requests_total counter
http_requests_total{code="200",method="post"} 1027 1395066363000
http_requests_total{code="400",method="post"} 3 1395066363000

metric_without_timestamp_and_labels 12.47

# HELP rpc_duration_seconds A summary of the RPC duration in seconds.
# TYPE rpc_duration_seconds summary
rpc_duration_seconds{quantile="0.01"} 3102
rpc_duration_seconds{quantile="0.05"} 3272
rpc_duration_seconds{quantile="0.5"} 4773
rpc_duration_seconds{quantile="0.9"} 9001
rpc_duration_seconds{quantile="0.99"} 76656
rpc_duration_seconds_sum 17560473
rpc_duration_seconds_count 2693

something_weird{problem="division by zero"} +Inf -3982045

Protobuf

Protobuf 是一种 Protocol Buffers 格式。

此格式需要一个外部格式模式。模式在查询之间被缓存。ClickHouse 支持 proto2proto3 语法。支持重复/可选/必填字段。

使用示例

SELECT * FROM test.table FORMAT Protobuf SETTINGS format_schema = 'schemafile:MessageType'
cat protobuf_messages.bin | clickhouse-client --query "INSERT INTO test.table SETTINGS format_schema='schemafile:MessageType' FORMAT Protobuf"

其中文件 schemafile.proto 内容如下

syntax = "proto3";

message MessageType {
string name = 1;
string surname = 2;
uint32 birthDate = 3;
repeated string phoneNumbers = 4;
};

为了找到表列与 Protocol Buffers 消息类型的字段之间的对应关系,ClickHouse 会比较它们的名称。此比较不区分大小写,并且字符 _(下划线)和 .(点)被视为相等。如果列和 Protocol Buffers 消息的字段类型不同,则会进行必要的转换。

支持嵌套消息。例如,对于以下消息类型中的字段 z

message MessageType {
message XType {
message YType {
int32 z;
};
repeated YType y;
};
XType x;
};

ClickHouse 会尝试查找名为 x.y.z(或 x_y_zX.y_Z 等)的列。嵌套消息适用于输入或输出 嵌套数据结构

在 protobuf 模式中定义的默认值,例如

syntax = "proto2";

message MessageType {
optional int32 result_per_page = 3 [default = 10];
}

不会被应用;表默认值 会代替它们。

ClickHouse 以 length-delimited 格式输入和输出 protobuf 消息。这意味着在每个消息之前,都需要以 varint 格式写入其长度。另请参见 如何在流行语言中读取/写入长度分隔的 protobuf 消息

使用自动生成的模式

如果您没有数据的外部 Protobuf 模式,您仍然可以使用自动生成的模式以 Protobuf 格式输出/输入数据。例如

SELECT * FROM test.hits format Protobuf SETTINGS format_protobuf_use_autogenerated_schema=1

在这种情况下,ClickHouse 会根据表结构使用函数 structureToProtobufSchema 自动生成 Protobuf 模式,并使用此模式以 Protobuf 格式序列化数据。

您也可以使用自动生成的模式读取 Protobuf 文件(在这种情况下,文件必须使用相同的模式创建)

$ cat hits.bin | clickhouse-client --query "INSERT INTO test.hits SETTINGS format_protobuf_use_autogenerated_schema=1 FORMAT Protobuf"

设置 format_protobuf_use_autogenerated_schema 默认情况下是启用的,并且如果 format_schema 未设置,则会应用此设置。

您还可以使用设置 output_format_schema 在输入/输出期间将自动生成的模式保存在文件中。例如

SELECT * FROM test.hits format Protobuf SETTINGS format_protobuf_use_autogenerated_schema=1, output_format_schema='path/to/schema/schema.proto'

在这种情况下,自动生成的 Protobuf 模式将保存在文件 path/to/schema/schema.capnp 中。

删除 Protobuf 缓存

要重新加载从 format_schema_path 加载的 Protobuf 模式,请使用 SYSTEM DROP ... FORMAT CACHE 语句。

SYSTEM DROP FORMAT SCHEMA CACHE FOR Protobuf

ProtobufSingle

Protobuf 相同,但用于存储/解析单个 Protobuf 消息,不包含长度分隔符。

ProtobufList

与 Protobuf 类似,但行表示为包含在具有固定名称“Envelope”的消息中的子消息序列。

使用示例

SELECT * FROM test.table FORMAT ProtobufList SETTINGS format_schema = 'schemafile:MessageType'
cat protobuflist_messages.bin | clickhouse-client --query "INSERT INTO test.table FORMAT ProtobufList SETTINGS format_schema='schemafile:MessageType'"

其中文件 schemafile.proto 内容如下

syntax = "proto3";
message Envelope {
message MessageType {
string name = 1;
string surname = 2;
uint32 birthDate = 3;
repeated string phoneNumbers = 4;
};
MessageType row = 1;
};

Avro

Apache Avro 是 Apache Hadoop 项目中开发的一种面向行的面向行数据序列化框架。

ClickHouse Avro 格式支持读取和写入 Avro 数据文件

数据类型匹配

下表显示了支持的数据类型以及它们在 INSERTSELECT 查询中与 ClickHouse 数据类型 的匹配方式。

Avro 数据类型 INSERTClickHouse 数据类型Avro 数据类型 SELECT
boolean, int, long, float, doubleInt(8\16\32), UInt(8\16\32)int
boolean, int, long, float, doubleInt64, UInt64long
boolean, int, long, float, doubleFloat32float
boolean, int, long, float, doubleFloat64double
bytes, string, fixed, enumStringbytesstring*
bytes, string, fixedFixedString(N)fixed(N)
enumEnum(8\16)enum
array(T)Array(T)array(T)
map(V, K)Map(V, K)map(string, K)
union(null, T), union(T, null)Nullable(T)union(null, T)
nullNullable(Nothing)null
int (date) **Date, Date32int (date) **
long (timestamp-millis) **DateTime64(3)long (timestamp-millis) **
long (timestamp-micros) **DateTime64(6)long (timestamp-micros) **
bytes (decimal) **DateTime64(N)bytes (decimal) **
intIPv4int
fixed(16)IPv6fixed(16)
bytes (decimal) **Decimal(P, S)bytes (decimal) **
string (uuid) **UUIDstring (uuid) **
fixed(16)Int128/UInt128fixed(16)
fixed(32)Int256/UInt256fixed(32)
recordTuplerecord

* bytes 是默认值,由 output_format_avro_string_column_pattern 控制** Avro 逻辑类型

不支持的 Avro 逻辑数据类型:time-millistime-microsduration

插入数据

要将 Avro 文件中的数据插入 ClickHouse 表中,请执行以下操作

$ cat file.avro | clickhouse-client --query="INSERT INTO {some_table} FORMAT Avro"

输入 Avro 文件的根模式必须为 record 类型。

为了找到表列与 Avro 模式字段之间的对应关系,ClickHouse 会比较它们的名称。此比较区分大小写。未使用的字段会被跳过。

ClickHouse 表列的数据类型可以与插入的 Avro 数据的相应字段不同。在插入数据时,ClickHouse 会根据上表解释数据类型,然后将数据 强制转换为 对应列类型。

在导入数据时,如果在模式中找不到字段,并且设置了 input_format_avro_allow_missing_fields,则会使用默认值,而不是出错。

选择数据

要从 ClickHouse 表中选择数据并将其保存到 Avro 文件中,请执行以下操作

$ clickhouse-client --query="SELECT * FROM {some_table} FORMAT Avro" > file.avro

列名必须

  • [A-Za-z_] 开头
  • 之后仅包含 [A-Za-z0-9_]

输出 Avro 文件的压缩和同步间隔可以通过 output_format_avro_codecoutput_format_avro_sync_interval 分别配置。

示例数据

使用 ClickHouse DESCRIBE 函数,您可以快速查看 Avro 文件的推断格式,例如以下示例。此示例包括 ClickHouse S3 公共存储桶中一个公开可访问的 Avro 文件的 URL

DESCRIBE url('https://clickhouse-public-datasets.s3.eu-central-1.amazonaws.com/hits.avro','Avro);
┌─name───────────────────────┬─type────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ WatchID │ Int64 │ │ │ │ │ │
│ JavaEnable │ Int32 │ │ │ │ │ │
│ Title │ String │ │ │ │ │ │
│ GoodEvent │ Int32 │ │ │ │ │ │
│ EventTime │ Int32 │ │ │ │ │ │
│ EventDate │ Date32 │ │ │ │ │ │
│ CounterID │ Int32 │ │ │ │ │ │
│ ClientIP │ Int32 │ │ │ │ │ │
│ ClientIP6 │ FixedString(16) │ │ │ │ │ │
│ RegionID │ Int32 │ │ │ │ │ │
...
│ IslandID │ FixedString(16) │ │ │ │ │ │
│ RequestNum │ Int32 │ │ │ │ │ │
│ RequestTry │ Int32 │ │ │ │ │ │
└────────────────────────────┴─────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘

AvroConfluent

AvroConfluent 支持解码通常与 KafkaConfluent Schema Registry 一起使用的单对象 Avro 消息。

每个 Avro 消息都嵌入一个模式 ID,可以使用 Schema Registry 将其解析为实际模式。

模式在解析后会被缓存。

Schema Registry URL 通过 format_avro_schema_registry_url 配置。

数据类型匹配

Avro 相同。

用法

要快速验证模式解析,可以使用 kafkacatclickhouse-local 一起使用

$ kafkacat -b kafka-broker  -C -t topic1 -o beginning -f '%s' -c 3 | clickhouse-local   --input-format AvroConfluent --format_avro_schema_registry_url 'http://schema-registry' -S "field1 Int64, field2 String"  -q 'select *  from table'
1 a
2 b
3 c

要将 AvroConfluentKafka 一起使用

CREATE TABLE topic1_stream
(
field1 String,
field2 String
)
ENGINE = Kafka()
SETTINGS
kafka_broker_list = 'kafka-broker',
kafka_topic_list = 'topic1',
kafka_group_name = 'group1',
kafka_format = 'AvroConfluent';

-- for debug purposes you can set format_avro_schema_registry_url in a session.
-- this way cannot be used in production
SET format_avro_schema_registry_url = 'http://schema-registry';

SELECT * FROM topic1_stream;
注意

需要在 users.xml 中配置 format_avro_schema_registry_url 设置,以便在重启后保持其值。您也可以使用 Kafka 表引擎的 format_avro_schema_registry_url 设置。

Parquet

Apache Parquet 是一种在 Hadoop 生态系统中广泛使用的列式存储格式。ClickHouse 支持此格式的读写操作。

数据类型匹配

下表显示了支持的数据类型以及它们在 INSERTSELECT 查询中与 ClickHouse 数据类型 的匹配方式。

Parquet 数据类型 (INSERT)ClickHouse 数据类型Parquet 数据类型 (SELECT)
BOOLBoolBOOL
UINT8, BOOLUInt8UINT8
INT8Int8/Enum8INT8
UINT16UInt16UINT16
INT16Int16/Enum16INT16
UINT32UInt32UINT32
INT32Int32INT32
UINT64UInt64UINT64
INT64Int64INT64
FLOATFloat32FLOAT
DOUBLEFloat64DOUBLE
DATEDate32DATE
TIME (ms)DateTimeUINT32
TIMESTAMP, TIME (us, ns)DateTime64TIMESTAMP
STRING, BINARYStringBINARY
STRING, BINARY, FIXED_LENGTH_BYTE_ARRAYFixedStringFIXED_LENGTH_BYTE_ARRAY
DECIMALDecimalDECIMAL
LISTArrayLIST
STRUCTTupleSTRUCT
MAPMapMAP
UINT32IPv4UINT32
FIXED_LENGTH_BYTE_ARRAY, BINARYIPv6FIXED_LENGTH_BYTE_ARRAY
FIXED_LENGTH_BYTE_ARRAY, BINARYInt128/UInt128/Int256/UInt256FIXED_LENGTH_BYTE_ARRAY

数组可以嵌套,并且可以将 Nullable 类型的值作为参数。TupleMap 类型也可以嵌套。

不支持的 Parquet 数据类型:FIXED_SIZE_BINARYJSONUUIDENUM

ClickHouse 表列的数据类型可以与插入的 Parquet 数据的相应字段不同。在插入数据时,ClickHouse 会根据上表解释数据类型,然后将数据 强制转换为 为 ClickHouse 表列设置的该数据类型。

插入和选择数据

您可以通过以下命令将 Parquet 数据从文件插入 ClickHouse 表中

$ cat {filename} | clickhouse-client --query="INSERT INTO {some_table} FORMAT Parquet"

您可以通过以下命令从 ClickHouse 表中选择数据并将其保存到 Parquet 格式的某个文件中

$ clickhouse-client --query="SELECT * FROM {some_table} FORMAT Parquet" > {some_file.pq}

要与 Hadoop 交换数据,您可以使用 HDFS 表引擎

Parquet 格式设置

ParquetMetadata {data-format-parquet-metadata}

用于读取 Parquet 文件元数据(https://parquet.apache.org/docs/file-format/metadata/)的特殊格式。它始终输出具有以下结构/内容的一行

  • num_columns - 列数
  • num_rows - 总行数
  • num_row_groups - 总行组数
  • format_version - parquet 格式版本,始终为 1.0 或 2.6
  • total_uncompressed_size - 数据的总未压缩字节大小,计算为所有行组的 total_byte_size 之和
  • total_compressed_size - 数据的总压缩字节大小,计算为所有行组的 total_compressed_size 之和
  • columns - 列元数据的列表,具有以下结构
    • name - 列名
    • path - 列路径(对于嵌套列,与名称不同)
    • max_definition_level - 最大定义级别
    • max_repetition_level - 最大重复级别
    • physical_type - 列物理类型
    • logical_type - 列逻辑类型
    • compression - 用于此列的压缩
    • total_uncompressed_size - 列的总未压缩字节大小,计算为所有行组中该列的 total_uncompressed_size 之和
    • total_compressed_size - 列的总压缩字节大小,计算为所有行组中该列的 total_compressed_size 之和
    • space_saved - 压缩节省的存储空间百分比,计算为 (1 - total_compressed_size/total_uncompressed_size)。
    • encodings - 用于此列的编码列表
  • row_groups - 行组元数据的列表,具有以下结构
    • num_columns - 行组中的列数
    • num_rows - 行组中的行数
    • total_uncompressed_size - 行组的总未压缩字节大小
    • total_compressed_size - 行组的总压缩字节大小
    • columns - 列块元数据的列表,具有以下结构
      • name - 列名
      • path - 列路径
      • total_compressed_size - 列的总压缩字节大小
      • total_uncompressed_size - 行组的总未压缩字节大小
      • have_statistics - 布尔标志,指示列块元数据是否包含列统计信息
      • statistics - 列块统计信息(如果 have_statistics = false,则所有字段均为 NULL),具有以下结构
        • num_values - 列块中非空值的个数
        • null_count - 列块中 NULL 值的个数
        • distinct_count - 列块中不同值的个数
        • min - 列块的最小值
        • max - 列块的最大值

示例

SELECT * FROM file(data.parquet, ParquetMetadata) format PrettyJSONEachRow
{
"num_columns": "2",
"num_rows": "100000",
"num_row_groups": "2",
"format_version": "2.6",
"metadata_size": "577",
"total_uncompressed_size": "282436",
"total_compressed_size": "26633",
"columns": [
{
"name": "number",
"path": "number",
"max_definition_level": "0",
"max_repetition_level": "0",
"physical_type": "INT32",
"logical_type": "Int(bitWidth=16, isSigned=false)",
"compression": "LZ4",
"total_uncompressed_size": "133321",
"total_compressed_size": "13293",
"space_saved": "90.03%",
"encodings": [
"RLE_DICTIONARY",
"PLAIN",
"RLE"
]
},
{
"name": "concat('Hello', toString(modulo(number, 1000)))",
"path": "concat('Hello', toString(modulo(number, 1000)))",
"max_definition_level": "0",
"max_repetition_level": "0",
"physical_type": "BYTE_ARRAY",
"logical_type": "None",
"compression": "LZ4",
"total_uncompressed_size": "149115",
"total_compressed_size": "13340",
"space_saved": "91.05%",
"encodings": [
"RLE_DICTIONARY",
"PLAIN",
"RLE"
]
}
],
"row_groups": [
{
"num_columns": "2",
"num_rows": "65409",
"total_uncompressed_size": "179809",
"total_compressed_size": "14163",
"columns": [
{
"name": "number",
"path": "number",
"total_compressed_size": "7070",
"total_uncompressed_size": "85956",
"have_statistics": true,
"statistics": {
"num_values": "65409",
"null_count": "0",
"distinct_count": null,
"min": "0",
"max": "999"
}
},
{
"name": "concat('Hello', toString(modulo(number, 1000)))",
"path": "concat('Hello', toString(modulo(number, 1000)))",
"total_compressed_size": "7093",
"total_uncompressed_size": "93853",
"have_statistics": true,
"statistics": {
"num_values": "65409",
"null_count": "0",
"distinct_count": null,
"min": "Hello0",
"max": "Hello999"
}
}
]
},
...
]
}

Arrow

Apache Arrow 带有两个内置的列式存储格式。ClickHouse 支持对这些格式的读写操作。

Arrow 是 Apache Arrow 的“文件模式”格式。它专为内存中的随机访问而设计。

数据类型匹配

下表显示了支持的数据类型以及它们在 INSERTSELECT 查询中与 ClickHouse 数据类型 的匹配方式。

Arrow 数据类型 (INSERT)ClickHouse 数据类型Arrow 数据类型 (SELECT)
BOOLBoolBOOL
UINT8, BOOLUInt8UINT8
INT8Int8/Enum8INT8
UINT16UInt16UINT16
INT16Int16/Enum16INT16
UINT32UInt32UINT32
INT32Int32INT32
UINT64UInt64UINT64
INT64Int64INT64
FLOAT, HALF_FLOATFloat32FLOAT32
DOUBLEFloat64FLOAT64
DATE32Date32UINT16
DATE64DateTimeUINT32
TIMESTAMP, TIME32, TIME64DateTime64UINT32
STRING, BINARYStringBINARY
STRING, BINARY, FIXED_SIZE_BINARYFixedStringFIXED_SIZE_BINARY
DECIMALDecimalDECIMAL
DECIMAL256Decimal256DECIMAL256
LISTArrayLIST
STRUCTTupleSTRUCT
MAPMapMAP
UINT32IPv4UINT32
FIXED_SIZE_BINARY, BINARYIPv6FIXED_SIZE_BINARY
FIXED_SIZE_BINARY, BINARYInt128/UInt128/Int256/UInt256FIXED_SIZE_BINARY

数组可以嵌套,并且可以将 Nullable 类型的值作为参数。TupleMap 类型也可以嵌套。

DICTIONARY 类型支持 INSERT 查询,而对于 SELECT 查询,有一个 output_format_arrow_low_cardinality_as_dictionary 设置允许将 LowCardinality 类型输出为 DICTIONARY 类型。

不支持的 Arrow 数据类型:FIXED_SIZE_BINARYJSONUUIDENUM

ClickHouse 表列的数据类型不必与相应的 Arrow 数据字段匹配。插入数据时,ClickHouse 会根据上表解释数据类型,然后将其 转换为 ClickHouse 表列中设置的数据类型。

插入数据

您可以使用以下命令将 Arrow 数据从文件插入 ClickHouse 表中

$ cat filename.arrow | clickhouse-client --query="INSERT INTO some_table FORMAT Arrow"

选择数据

您可以使用以下命令从 ClickHouse 表中选择数据并将其保存到 Arrow 格式的某个文件中

$ clickhouse-client --query="SELECT * FROM {some_table} FORMAT Arrow" > {filename.arrow}

Arrow 格式设置

ArrowStream

ArrowStream 是 Apache Arrow 的“流模式”格式。它专为内存中的流处理而设计。

ORC

Apache ORC 是一种在 Hadoop 生态系统中广泛使用的列式存储格式。

数据类型匹配

下表显示了支持的数据类型以及它们在 INSERTSELECT 查询中与 ClickHouse 数据类型 的匹配方式。

ORC 数据类型 (INSERT)ClickHouse 数据类型ORC 数据类型 (SELECT)
BooleanUInt8Boolean
TinyintInt8/UInt8/Enum8Tinyint
SmallintInt16/UInt16/Enum16Smallint
IntInt32/UInt32Int
BigintInt64/UInt32Bigint
FloatFloat32Float
DoubleFloat64Double
DecimalDecimalDecimal
DateDate32Date
TimestampDateTime64Timestamp
String, Char, Varchar, BinaryStringBinary
ListArrayList
StructTupleStruct
MapMapMap
IntIPv4Int
BinaryIPv6Binary
BinaryInt128/UInt128/Int256/UInt256Binary
BinaryDecimal256Binary

其他类型不支持。

数组可以嵌套,并且可以将 Nullable 类型的值作为参数。TupleMap 类型也可以嵌套。

ClickHouse 表列的数据类型不必与相应的 ORC 数据字段匹配。插入数据时,ClickHouse 会根据上表解释数据类型,然后将其 转换为 ClickHouse 表列中设置的数据类型。

插入数据

您可以使用以下命令将 ORC 数据从文件插入 ClickHouse 表中

$ cat filename.orc | clickhouse-client --query="INSERT INTO some_table FORMAT ORC"

选择数据

您可以使用以下命令从 ClickHouse 表中选择数据并将其保存到 ORC 格式的某个文件中

$ clickhouse-client --query="SELECT * FROM {some_table} FORMAT ORC" > {filename.orc}

Arrow 格式设置

要与 Hadoop 交换数据,您可以使用 HDFS 表引擎

One

一种特殊输入格式,它不从文件中读取任何数据,只返回一行数据,该行数据包含一个类型为 UInt8、名为 dummy 且值为 0 的列(类似于 system.one 表)。可以与虚拟列 _file/_path 一起使用,列出所有文件而不读取实际数据。

示例

查询

SELECT _file FROM file('path/to/files/data*', One);

结果

┌─_file────┐
│ data.csv │
└──────────┘
┌─_file──────┐
│ data.jsonl │
└────────────┘
┌─_file────┐
│ data.tsv │
└──────────┘
┌─_file────────┐
│ data.parquet │
└──────────────┘

Npy

此函数旨在将 NumPy 数组从 .npy 文件加载到 ClickHouse。NumPy 文件格式是一种二进制格式,用于有效存储数值数据的数组。导入期间,ClickHouse 将顶层维度视为具有单个列的行数组。支持的 Npy 数据类型及其在 ClickHouse 中的对应类型

Npy 数据类型 (INSERT)ClickHouse 数据类型Npy 数据类型 (SELECT)
i1Int8i1
i2Int16i2
i4Int32i4
i8Int64i8
u1, b1UInt8u1
u2UInt16u2
u4UInt32u4
u8UInt64u8
f2, f4Float32f4
f8Float64f8
S, UStringS
FixedStringS

使用 Python 将数组保存为 .npy 格式的示例

import numpy as np
arr = np.array([[[1],[2],[3]],[[4],[5],[6]]])
np.save('example_array.npy', arr)

在 ClickHouse 中读取 NumPy 文件的示例

查询

SELECT *
FROM file('example_array.npy', Npy)

结果

┌─array─────────┐
│ [[1],[2],[3]] │
│ [[4],[5],[6]] │
└───────────────┘

选择数据

您可以使用以下命令从 ClickHouse 表中选择数据并将其保存到 Npy 格式的某个文件中

$ clickhouse-client --query="SELECT {column} FROM {some_table} FORMAT Npy" > {filename.npy}

LineAsString

在此格式中,输入数据的每一行都被解释为单个字符串值。此格式只能解析具有单个 String 类型字段的表。其余列必须设置为 DEFAULTMATERIALIZED,或者省略。

示例

查询

DROP TABLE IF EXISTS line_as_string;
CREATE TABLE line_as_string (field String) ENGINE = Memory;
INSERT INTO line_as_string FORMAT LineAsString "I love apple", "I love banana", "I love orange";
SELECT * FROM line_as_string;

结果

┌─field─────────────────────────────────────────────┐
│ "I love apple", "I love banana", "I love orange"; │
└───────────────────────────────────────────────────┘

Regexp

导入数据的每一行都根据正则表达式进行解析。

在使用 Regexp 格式时,您可以使用以下设置

  • format_regexp字符串。包含 re2 格式的正则表达式。

  • format_regexp_escaping_rule字符串。支持以下转义规则

    • CSV(类似于 CSV
    • JSON(类似于 JSONEachRow
    • 转义(类似于 TSV
    • 引用(类似于 Values
    • 原始(将子模式作为一个整体提取,没有转义规则,类似于 TSVRaw
  • format_regexp_skip_unmatchedUInt8。定义在 format_regexp 表达式与导入数据不匹配的情况下是否需要抛出异常。可以设置为 01

用法

来自 format_regexp 设置的正则表达式将应用于导入数据的每一行。正则表达式中的子模式数量必须等于导入数据集中的列数。

导入数据的行必须以换行符 '\n' 或 DOS 风格换行符 "\r\n" 分隔。

每个匹配的子模式的内容将根据 format_regexp_escaping_rule 设置,使用相应数据类型的解析方法解析。

如果正则表达式与该行不匹配,并且 format_regexp_skip_unmatched 设置为 1,则该行将被静默跳过。否则,将抛出异常。

示例

考虑文件 data.tsv

id: 1 array: [1,2,3] string: str1 date: 2020-01-01
id: 2 array: [1,2,3] string: str2 date: 2020-01-02
id: 3 array: [1,2,3] string: str3 date: 2020-01-03

和表

CREATE TABLE imp_regex_table (id UInt32, array Array(UInt32), string String, date Date) ENGINE = Memory;

导入命令

$ cat data.tsv | clickhouse-client  --query "INSERT INTO imp_regex_table SETTINGS format_regexp='id: (.+?) array: (.+?) string: (.+?) date: (.+?)', format_regexp_escaping_rule='Escaped', format_regexp_skip_unmatched=0 FORMAT Regexp;"

查询

SELECT * FROM imp_regex_table;

结果

┌─id─┬─array───┬─string─┬───────date─┐
│ 1 │ [1,2,3] │ str1 │ 2020-01-01 │
│ 2 │ [1,2,3] │ str2 │ 2020-01-02 │
│ 3 │ [1,2,3] │ str3 │ 2020-01-03 │
└────┴─────────┴────────┴────────────┘

格式模式

包含格式模式的文件名由设置 format_schema 设置。当使用 Cap'n ProtoProtobuf 格式之一时,需要设置此设置。格式模式是文件名和此文件中消息类型的名称的组合,以冒号分隔,例如 schemafile.proto:MessageType。如果该文件具有该格式的标准扩展名(例如,Protobuf.proto),则可以省略,在这种情况下,格式模式将类似于 schemafile:MessageType

如果您在 客户端交互模式 中通过输入或输出数据,格式模式中指定的文件名可以包含绝对路径或相对于客户端当前目录的路径。如果您在 批处理模式 中使用客户端,由于安全原因,模式的路径必须是相对的。

如果您通过 HTTP 接口 输入或输出数据,格式模式中指定的文件名应位于服务器配置中 format_schema_path 指定的目录中。

跳过错误

某些格式(如 CSVTabSeparatedTSKVJSONEachRowTemplateCustomSeparatedProtobuf)如果解析错误发生,可以跳过损坏的行并从下一行的开头继续解析。请参阅 input_format_allow_errors_numinput_format_allow_errors_ratio 设置。限制

  • 如果解析错误,JSONEachRow 将跳过所有数据,直到出现新行(或 EOF),因此行必须以 \n 分隔才能正确计算错误。
  • TemplateCustomSeparated 使用最后一列后面的分隔符和行之间的分隔符来查找下一行的开头,因此跳过错误仅在其中一个为空时才有效。

RawBLOB

在此格式中,所有输入数据都将读取到单个值中。只能解析具有单个类型为 字符串 或类似的字段的表。结果以二进制格式输出,不包含分隔符和转义。如果输出多个值,则格式不明确,无法读取回数据。

以下是 RawBLOBTabSeparatedRaw 格式的比较。

RawBLOB:

  • 数据以二进制格式输出,不包含转义;
  • 值之间没有分隔符;
  • 每个值末尾没有换行符。

TabSeparatedRaw:

  • 数据以不含转义的格式输出;
  • 行包含以制表符分隔的值;
  • 每行的最后一个值后面都有一个换行符。

以下是 RawBLOBRowBinary 格式的比较。

RawBLOB:

  • 字符串字段输出时不以长度为前缀。

RowBinary:

当将空数据传递给 RawBLOB 输入时,ClickHouse 会抛出异常

Code: 108. DB::Exception: No data to insert

示例

$ clickhouse-client --query "CREATE TABLE {some_table} (a String) ENGINE = Memory;"
$ cat {filename} | clickhouse-client --query="INSERT INTO {some_table} FORMAT RawBLOB"
$ clickhouse-client --query "SELECT * FROM {some_table} FORMAT RawBLOB" | md5sum

结果

f9725a22f9191e064120d718e26862a9  -

MsgPack

ClickHouse 支持读取和写入 MessagePack 数据文件。

数据类型匹配

MessagePack 数据类型 (INSERT)ClickHouse 数据类型MessagePack 数据类型 (SELECT)
uint N, positive fixintUIntNuint N
int N, negative fixintIntNint N
boolUInt8uint 8
fixstr, str 8, str 16, str 32, bin 8, bin 16, bin 32Stringbin 8, bin 16, bin 32
fixstr, str 8, str 16, str 32, bin 8, bin 16, bin 32FixedStringbin 8, bin 16, bin 32
float 32Float32float 32
float 64Float64float 64
uint 16Dateuint 16
int 32Date32int 32
uint 32DateTimeuint 32
uint 64DateTime64uint 64
fixarray, array 16, array 32Array/Tuplefixarray, array 16, array 32
fixmap, map 16, map 32Mapfixmap, map 16, map 32
uint 32IPv4uint 32
bin 8Stringbin 8
int 8Enum8int 8
bin 8(U)Int128/(U)Int256bin 8
int 32Decimal32int 32
int 64Decimal64int 64
bin 8Decimal128/Decimal256bin 8

示例

写入文件 ".msgpk"

$ clickhouse-client --query="CREATE TABLE msgpack (array Array(UInt8)) ENGINE = Memory;"
$ clickhouse-client --query="INSERT INTO msgpack VALUES ([0, 1, 2, 3, 42, 253, 254, 255]), ([255, 254, 253, 42, 3, 2, 1, 0])";
$ clickhouse-client --query="SELECT * FROM msgpack FORMAT MsgPack" > tmp_msgpack.msgpk;

MsgPack 格式设置

MySQLDump

ClickHouse 支持读取 MySQL 转储。它从属于转储中一个表的 INSERT 查询中读取所有数据。如果有多个表,默认情况下它会从第一个表中读取数据。您可以使用 input_format_mysql_dump_table_name 设置指定要从其中读取数据的表名。如果设置 input_format_mysql_dump_map_columns 设置为 1 并且转储包含指定表的 CREATE 查询或 INSERT 查询中的列名,则来自输入数据的列将根据其名称映射到来自表的列,如果设置 input_format_skip_unknown_fields 设置为 1,则将跳过具有未知名称的列。此格式支持模式推断:如果转储包含指定表的 CREATE 查询,则从其中提取结构,否则从 INSERT 查询的数据中推断模式。

示例

文件 dump.sql

/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `test` (
`x` int DEFAULT NULL,
`y` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO `test` VALUES (1,NULL),(2,NULL),(3,NULL),(3,NULL),(4,NULL),(5,NULL),(6,7);
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `test 3` (
`y` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO `test 3` VALUES (1);
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `test2` (
`x` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO `test2` VALUES (1),(2),(3);

查询

DESCRIBE TABLE file(dump.sql, MySQLDump) SETTINGS input_format_mysql_dump_table_name = 'test2'
┌─name─┬─type────────────┬─default_type─┬─default_expression─┬─comment─┬─codec_expression─┬─ttl_expression─┐
│ x │ Nullable(Int32) │ │ │ │ │ │
└──────┴─────────────────┴──────────────┴────────────────────┴─────────┴──────────────────┴────────────────┘
SELECT *
FROM file(dump.sql, MySQLDump)
SETTINGS input_format_mysql_dump_table_name = 'test2'
┌─x─┐
│ 1 │
│ 2 │
│ 3 │
└───┘

DWARF

从 ELF 文件(可执行文件、库或目标文件)解析 DWARF 调试符号。类似于 dwarfdump,但速度更快(数百 MB/s)并且可以使用 SQL。为 .debug_info 部分中的每个调试信息条目 (DIE) 生成一行。包括 DWARF 编码用来终止树中子列表的“null”条目。

快速背景:.debug_info单元组成,对应于编译单元。每个单元都是DIE 的树,以 compile_unit DIE 作为根。每个 DIE 都有一个标记和一个属性列表。每个属性都有一个名称和一个(以及一个形式,它指定值的编码方式)。DIE 表示来自源代码的东西,它们的标记告诉它是哪种类型的东西。例如,有函数(标记 = subprogram)、类/结构体/枚举(class_type/structure_type/enumeration_type)、变量(variable)、函数参数(formal_parameter)。树结构反映了相应的源代码。例如,class_type DIE 可以包含表示该类方法的 subprogram DIE。

输出以下列

  • offset - DIE 在 .debug_info 部分中的位置
  • size - 编码的 DIE 中的字节数(包括属性)
  • tag - DIE 的类型;省略了传统的“DWTAG”前缀
  • unit_name - 包含此 DIE 的编译单元的名称
  • unit_offset - 包含此 DIE 的编译单元在 .debug_info 部分中的位置
  • ancestor_tags - 树中当前 DIE 的祖先标记的数组,从最内层到最外层排序
  • ancestor_offsets - 祖先的偏移量,与 ancestor_tags 并行
  • 为了方便起见,从属性数组中复制了一些常见的属性
    • name
    • linkage_name - 经过修饰的完全限定名称;通常只有函数有它(但并非所有函数都有)
    • decl_file - 声明此实体的源代码文件的名称
    • decl_line - 声明此实体的源代码中的行号
  • 描述属性的并行数组
    • attr_name - 属性的名称;省略了传统的“DWAT”前缀
    • attr_form - 属性的编码和解释方式;省略了传统的 DWFORM 前缀
    • attr_int - 属性的整数值;如果属性没有数值,则为 0
    • attr_str - 属性的字符串值;如果属性没有字符串值,则为空

示例:查找具有最多函数定义(包括模板实例化和来自包含头文件的函数)的编译单元

SELECT
unit_name,
count() AS c
FROM file('programs/clickhouse', DWARF)
WHERE tag = 'subprogram' AND NOT has(attr_name, 'declaration')
GROUP BY unit_name
ORDER BY c DESC
LIMIT 3
┌─unit_name──────────────────────────────────────────────────┬─────c─┐
│ ./src/Core/Settings.cpp │ 28939 │
│ ./src/AggregateFunctions/AggregateFunctionSumMap.cpp │ 23327 │
│ ./src/AggregateFunctions/AggregateFunctionUniqCombined.cpp │ 22649 │
└────────────────────────────────────────────────────────────┴───────┘

3 rows in set. Elapsed: 1.487 sec. Processed 139.76 million rows, 1.12 GB (93.97 million rows/s., 752.77 MB/s.)
Peak memory usage: 271.92 MiB.

Markdown

您可以使用 Markdown 格式导出结果,以生成可粘贴到您的 .md 文件中的输出

SELECT
number,
number * 2
FROM numbers(5)
FORMAT Markdown
| number | multiply(number, 2) |
|-:|-:|
| 0 | 0 |
| 1 | 2 |
| 2 | 4 |
| 3 | 6 |
| 4 | 8 |

Markdown 表格将自动生成,并且可以在支持 Markdown 的平台(如 Github)上使用。此格式仅用于输出。

Form

Form 格式可用于以 application/x-www-form-urlencoded 格式读取或写入单个记录,其中数据格式为 key1=value1&key2=value2

示例

假设在 user_files 路径中放置了一个名为 data.tmp 的文件,其中包含一些 URL 编码的数据

t_page=116&c.e=ls7xfkpm&c.tti.m=raf&rt.start=navigation&rt.bmr=390%2C11%2C10
SELECT * FROM file(data.tmp, Form) FORMAT vertical;

结果

Row 1:
──────
t_page: 116
c.e: ls7xfkpm
c.tti.m: raf
rt.start: navigation
rt.bmr: 390,11,10