clickhouse-local 或 S3 bucket;也可在将数据加载到 ClickHouse 之前自动创建 schema。
何时使用类型推断
- 结构一致 - 用于推断类型的数据应包含你关注的所有键。类型推断基于对数据的采样,最多读取最大行数或最大字节数。样本之后如果出现包含额外列的数据,将被忽略,且无法查询。
- 类型一致 - 特定键的数据类型需要相互兼容,即必须能够将一种类型自动强制转换为另一种类型。
检测类型
NDJSON。本节将探讨一个更复杂、包含嵌套结构的数据集——包含 250 万篇学术论文的 arXiv dataset。该数据集以 NDJSON 格式提供,其中每一行都表示一篇已发表的学术论文。下面展示了一个示例行:
Tuple 和 Array 等复杂类型。
该数据集存储在公共 S3 bucket s3://datasets-documentation/arxiv/arxiv.json.gz 中。
可以看到,上述数据集包含嵌套的 JSON 对象。虽然您应当起草并对 schema 进行版本管理,但 schema 推断 支持从数据中推断类型。这样就可以自动生成 schema DDL,无需手动构建,从而加快开发过程。
自动格式检测除了检测 schema 之外,JSON schema 推断 还会根据文件扩展名和内容自动推断数据的格式。因此,上述文件会被自动识别为 NDJSON。
DESCRIBE 命令,可以显示将被推断出的类型。
避免使用 NULL 值你可以看到,很多列都被识别为 Nullable。除非绝对必要,否则我们不建议使用 Nullable 类型。你可以使用 schema_inference_make_columns_nullable 来控制何时应用 Nullable。
String,而 update_date 列被正确识别为 Date。versions 列被创建为 Array(Tuple(created String, version String)),用于存储对象列表;authors_parsed 则被定义为 Array(Array(String)),用于表示嵌套数组。
控制类型检测日期和日期时间的自动检测分别可通过设置
input_format_try_infer_dates 和 input_format_try_infer_datetimes 进行控制 (两者默认均启用) 。将对象推断为 Tuple 的行为由设置 input_format_json_try_infer_named_tuples_from_objects 控制。其他控制 JSON schema 推断 的设置 (例如数值的自动检测) 可在此处查看。查询 JSON
创建表
CREATE AS EMPTY 命令会推断出该表的 DDL 并创建该表。此操作不会加载任何数据:
SHOW CREATE TABLE 命令:
input_format_max_rows_to_read_for_schema_inference (默认为 25000) 和 input_format_max_bytes_to_read_for_schema_inference (默认为 32MB) 控制。如果检测结果不正确,您可以按此处所述提供提示。
根据片段创建表
加载 JSON 数据
INSERT INTO SELECT 将数据插入该表:
PrettyJSONEachRow 格式,以原始结构显示各行:
处理错误
input_format_allow_errors_num 和 input_format_allow_errors_ratio,以便在数据触发插入错误时允许忽略一定数量的行。此外,还可以提供提示来辅助推断。
处理半结构化和动态数据
JSON 类型来处理这种情况。
如果你知道自己的 JSON 非常动态,包含大量唯一键,并且同一个键可能对应多种类型,我们建议不要使用 JSONEachRow 的 schema inference 来尝试为每个键推断出一列——即使数据采用的是以换行分隔的 JSON 格式也是如此。
请看下面这个示例,它来自前述 Python PyPI dataset 数据集的扩展版本。这里我们添加了一个任意的 tags 列,其中包含随机的键值对。
JSONEachRow 格式。它会尝试为 JSON 中的每个键推断对应的列类型——本质上是在不使用 JSON 类型的情况下,试图对数据套用静态 schema。
当存在成千上万个唯一列时,这种推断方式会很慢。作为替代,你可以使用 JSONAsObject 格式。
JSONAsObject 会将整个输入视为单个 JSON 对象,并将其存储到一个类型为 JSON 的列中,因此更适合高度动态或嵌套的 JSON 载荷。
sample.json 文件,其内容为以下以换行分隔的 JSON:
a 处理为 Nullable(String)。
类型强制转换这种类型强制转换可通过多个设置项来控制。上面的示例取决于设置
input_format_json_read_numbers_as_strings。DESCRIBE 命令会失败:
JSONAsObject 会将每一行视为单个 JSON 类型 (即支持同一列包含多种类型) 。这一点至关重要: