首页 > 解决方案 > ClickHouse:如何正确存储 JSON 数据?

问题描述

我打算将数据从 PostgreSQL 数据库迁移到 Yandex 的 ClickHouse。源表中的字段之一是 JSON 类型 - 称为additional_data. 因此,PostgreSQL 允许我在查询等期间访问 json 属性SELECT ...->>->

我需要相同的行为才能保留在 ClickHouse 存储中的结果表中。(即在选择查询和/或使用过滤和聚合子句时解析 JSON 的能力)

这是我CREATE TABLE ...在 ClickHouse 客户端中所做的事情:

create table if not exists analytics.events
(
    uuid UUID,
    ...,
    created_at DateTime,
    updated_at DateTime,
    additional_data Nested (
        message Nullable(String),
        eventValue Nullable(String),
        rating Nullable(String),
        focalLength Nullable(Float64)
        )
)
engine = MergeTree

ORDER BY (uuid, created_at)
PRIMARY KEY uuid;

如何存储 JSON 可序列化数据是一个不错的选择吗?有任何想法吗?

也许最好将 JSON 数据存储为普通数据,String而不是Nested使用特殊功能来使用它?

标签: sqlclickhouseyandexyandex-metrika

解决方案


  1. 虽然 ClickHouse 使用快速 JSON 库(例如simdjsonrapidjson)进行解析,但我认为 Nesting-fields 应该更快。

  2. 如果 JSON 结构是固定的或可预测地更改,请尝试考虑非规范化数据的方式:

..
    created_at DateTime,
    updated_at DateTime,
    additional_data_message Nullable(String),
    additional_data_eventValue Nullable(String),
    additional_data_rating Nullable(String),
    additional_data_focalLength Nullable(Float64)
..

一方面,它可以显着增加行数和磁盘空间,另一方面,它应该显着提高性能(尤其是在正确的索引中)。此外,可以使用LowCardinality-typeCodecs减小磁盘大小。

  1. 其他一些评论:
..
ORDER BY (created_at, uuid);
  • 考虑使用聚合引擎来显着提高计算聚合值的速度
  1. 在任何情况下,在做出最终决定之前都需要对数据子集进行手动测试(这适用于选择模式(json 作为字符串/嵌套类型/非规范化方式),作为选择列编解码器)。

推荐阅读