暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

高性价比OLAP列式数据库—Clickhouse(建表优化)

迷三张 2025-02-21
131
    在 ClickHouse 中,建表的优化是性能调优的重要环节。ClickHouse 是一个列式存储数据库,其性能高度依赖于表结构设计、数据分区、索引以及存储引擎的选择。以下是一些关键的建表优化点和最佳实践
数据类型

1、时间字段的类型

    建表时能用数值型或日期时间型表示的字段就不要用字符串,全 String 类型在以 Hive为中心的数仓建设中常见,但 ClickHouse 环境不应受此影响。

    虽然 ClickHouse 底层将 DateTime 存储为时间戳 Long 类型,但不建议存储 Long 类型,因为 DateTime 不需要经过函数转换处理,执行效率高、可读性好

    create table t_type_test(
     id UInt32,
     sku_id String,
     total_amount Decimal(16,2) ,
     create_time Int32 
    ) engine =ReplacingMergeTree(create_time)
     partition by toYYYYMMDD(toDate(create_time)) –-需要转换一次,否则报错
     primary key (id)
     order by (id, sku_id);
    2、空指存储类型

        要在表的列中存储 Nullable
     类型值,ClickHouse 除了使用带有值的普通文件外,还使用带有 NULL
     掩码的单独文件。 掩码文件中的条目允许 ClickHouse 区分每个表行的 NULL
     和相应数据类型的默认值。 由于附加了新文件,Nullable
     列与类似的普通文件相比消耗额外的存储空间。使用 Nullable 几乎总是对性能产生负面影响。因此除非极特殊情况,应直接使用字段默认值表示空,或者自行指定一个在业务中无意义的值(例如用-1 表示没有商品ID)。

      CREATE TABLE nullable (`n` Nullable(UInt32)) ENGINE = MergeTree ORDER BY tuple();


      INSERT INTO nullable VALUES (1) (NULL) (2) (NULL);


      SELECT n.null FROM nullable; 
        ┌─n.null─┐
        │      0 │
        │      1 │
        │      0 │
        │      1 │
        └────────┘
        查看文件

        https://clickhouse.com/docs/zh/sql-reference/data-types/nullable

        ClickHouse官网说明

        分区和索引

            分区粒度根据业务特点决定,不宜过粗或过细,分区过多会导致元数据膨胀,影响性能。一般选择按天分区,也可以指定为 Tuple(),以单表一亿数据为例,分区大小控制在 10-30 个为最佳。

            必须指定索引列,ClickHouse 中的索引列即排序列,通过 order by 指定,一般在查询条件中经常被用来充当筛选条件的属性被纳入进来;可以是单一维度,也可以是组合维度的索引;通常需要满足高级列在前、查询频率大的在前原则;还有基数特别大的不适合做索引列,如用户表的 userid 字段;通常筛选后的数据满足在百万以内为最佳

        比如官方案例的 hits_v1 表:

          PARTITION BY toYYYYMM(EventDate)
          ORDER BY (CounterID, EventDate, intHash32(UserID))

          visits_v1 表:

            PARTITION BY toYYYYMM(StartDate)
            ORDER BY (CounterID, StartDate, intHash32(UserID), VisitID)

            表参数

                Index_granularity 是用来控制索引粒度的,默认是 8192,如非必须不建议调整。

                如果表中不是必须保留全量历史数据,建议指定 TTL(生存时间值),可以免去手动过期历史数据的麻烦,TTL 也可以通过 alter table 语句随时修改。(参考基础文档 4.4.5 数据 TTL


            写入和删除优化

                尽量不要执行单条或小批量删除和插入操作,这样会产生小分区文件,给后台Merge 任务带来巨大压力

                不要一次写入太多分区,或数据写入太快,数据写入太快会导致 Merge 速度跟不上而报错,一般建议每秒钟发起 2-3 次写入操作,每次操作写入 2w~5w 条数据(依服务器性能而定

            写入过快报错,报错信息:

              1Code252, e.displayText() = DB::Exception: Too many parts(304). 
              Merges are processing significantly slower than inserts
              2. Code: 241, e.displayText() = DB::Exception: Memory limit (for query) 
              exceeded:would use 9.37 GiB (attempt to allocate chunk of 301989888 
              bytes), maximum: 9.31 GiB

              处理方式:

                   “ Too many parts 处理 ” :使用 WAL 预写日志,提高写入性能。in_memory_parts_enable_wal 默认为 true。

                 在服务器内存充裕的情况下增加内存配额,一般通过 max_memory_usage 来实现;在服务器内存不充裕的情况下,建议将超出部分内容分配到系统硬盘上,但会降低执行速度,一般通过max_bytes_before_external_group_bymax_bytes_before_external_sort 参数来实现。


              常见配置

                  配置项主要在 config.xml 或 users.xml 中, 基本上都在 users.xml 

              • config.xml 的配置项

                  https://clickhouse.tech/docs/en/operations/server-configuration-parameters/settings/

              • users.xml 的配置项

                  https://clickhouse.tech/docs/en/operations/settings/settings/


              存储

                  ClickHouse 不支持设置多数据目录,为了提升数据 io 性能,可以挂载虚拟卷组,一个卷组绑定多块物理磁盘提升读写性能,多数据查询场景 SSD 会比普通机械硬盘快 2-3 倍。

              文章转载自迷三张,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

              评论