Clickhouse学习笔记(8)—— 建表优化

数据类型

时间字段

建表时能用数值型或日期时间类型(DateTime)表示的字段就不要用字符串

因为clickhouse进行分区时一般使用时间字段来进行分区,而将时间字段使用DateTime表示,不需要经过函数转换处理,执行效率高、可读性好

如以下建表语句:

sql 复制代码
create table t_date_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);

这里的create_time使用了Int32类型来保存,因此在使用toYYYYMMDD函数进行格式转换时需要使用toDate来进行处理,否则会报错:

空值存储类型

clickhouse中不建议使用Nullable 类型,因为其会对性能造成影响;

先创建一张有Nullable类型字段的表:

sql 复制代码
CREATE TABLE t_null(x Int8, y Nullable(Int8)) ENGINE TinyLog;

其中Nullable(Int8)说明该字段可以是null,也可以是int8类型的数据;

然后向其中插入两条数据:

sql 复制代码
INSERT INTO t_null VALUES (1, NULL), (2, 3);

然后进入/var/lib/clickhouse/data/default/t_null路径下查看:

发现多出来了一个数据文件来专门存储null类型的数据,这会对查询性能造成影响;

而且Nullable 列无法被索引,因此除非极特殊情况,应直接使用字段默认值表示空,或者自行指定一个在业务中无意义的值(例如用-1 表示没有商品ID)

官网说明如下:Nullable(typename) | ClickHouse Docs

分区

分区粒度根据业务特点决定,不宜过粗或过细。一般选择按天分区,以单表一亿数据为例,分区大小控制在 10-30 个为最佳

索引

必须指定索引列,ClickHouse 中的索引列即排序列,通过 order by 指定

通常需要满足高级列在前、查询频率大的在前原则

而且基数特别大的不适合做索引列,如用户表的 userid 字段

表参数

  • Index_granularity 是用来控制索引粒度的,默认是 8192 ,如非必须不建议调整(该默认值适用于官方示例的单表一亿数据情况下)
  • 如果表中不是必须保留全量历史数据,建议指定 TTL(生存时间值),可以免去手动过期历史数据的麻烦,TTL 也可以通过 alter table 语句随时修改

写入和删除优化

  • 尽量不要执行单条或小批量删除和插入操作,这样会产生小分区文件,给后台Merge 任务带来巨大压力(需要攒批)
  • 不要一次写入太多分区,或数据写入太快,数据写入太快会导致 Merge 速度跟不上而报错,一般建议每秒钟发起 2-3 次写入操作,每次操作写入 2w~5w 条数据(依服务器性能而定)

如果写入过快的话可能出现的报错信息:

bash 复制代码
1. Code: 252, 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

常见配置

clickhouse的配置文件路径:/etc/clickhouse-server

主要的配置文件有两个:

users.xmlUser Settings | ClickHouse Docs

config.xmlGlobal Server Settings | ClickHouse Docs

大多数内容都在config.xml配置文件中;

CPU资源

clickhouse由于多线程执行,对于CPU的占用率很高,因此尽量单独部署,不要和Hadoop集群部署到一台机器上,以免运行时占用其他服务的资源

常用参数如下:

|-------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 配置 | 描述 |
| background_pool_size | 后台线程池的大小,merge 线程就是在该线程池中执行,该线程池不仅仅是给 merge 线程用的,默认值 16,允许的前提下建议改成 cpu 个数的 2 倍(线程数) |
| background_schedule_pool_size | 执行一些轻量级周期性操作(后台任务) (复制表、Kafka 流、DNS 缓存更新)的线程数;默认值 128,建议改成 cpu 个数的 2 倍(线程数) |
| background_distributed_schedule_pool_size | 设置为分布式 发送执行后台任务的线程数,默认 16,建议改成 cpu个数的 2 倍(线程数) |
| max_concurrent_queries | 最大并发处理 的请求数(包含select,insert 等),默认值 100,推荐 150(不够再加)~300 (最新版本的默认值是0(2023),表示不进行限制) (该参数可以在运行环境中进行修改且立即生效,但不适用于修改时正在运行的任务) |
| max_threads | 设置单个查询所能使用的最大 cpu 个数,默认是 cpu 核数 Core Settings | ClickHouse Docs |

除了max_threads需要使用set param=value的方式设置外,其余参数均可在config.xml文件中设置

内存资源

|------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 配置 | 描述 |
| max_memory_usage | 此参数在 users.xml,表示单次 Query 占用内存最大值,该值可以设置的比较大,这样可以提升集群查询的上限。(默认值是10G) 应当保留一点给 OS,比如 128G 内存的机器,设置为 100GB 这也是clickhouse推荐单机部署的原因之一,因为如果和yarn等组件部署在一台机器上,该值无法设置的比较大 |
| max_bytes_before_external_group_by | 一般按照 max_memory_usage 的一半 设置内存,当 group by使用内存超过阈值后会刷新到磁盘进行 因为 clickhouse 聚合分两个阶段:查询并及建立中间数据、合并中间数据,结合上一项,建议 50GB 这样的话如果内存不够用也不会报错,而是会把内存中的数据先刷写到磁盘上,然后继续执行,不过会大幅降低执行效率(实测降低效率十分严重,一般无法接收) Restrictions on Query Complexity | ClickHouse Docs 通过set param=value可设置 |
| max_bytes_before_external_sort | 当 order by 已使用 max_bytes_before_external_sort 内存就进行溢写磁盘(基于磁盘排序) 与上一个参数类似 通过set param=value可设置 |
| max_table_size_to_drop | 此参数在config.xml 中,应用于需要删除表或分区的情况,默认是50GB,意思是如果删除 50GB 以上的分区表会失败。建议修改为 0,这样不管多大的分区表都可以删除 |

存储

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

参数配置总结

大部分参数在config.xml中可配置,与用户相关的优先查找users.xml

如果都没有找到,则可以通过show settings like '参数名'的方式查找;

与参数配置相关的文档有:

Global Server Settings | ClickHouse Docs

Core Settings | ClickHouse Docs

User Settings | ClickHouse Docs

相关推荐
康熙38bdc1 分钟前
Linux 环境变量
linux·运维·服务器
一丝晨光2 分钟前
Java、PHP、ASP、JSP、Kotlin、.NET、Go
java·kotlin·go·php·.net·jsp·asp
罗曼蒂克在消亡6 分钟前
2.3MyBatis——插件机制
java·mybatis·源码学习
存储服务专家StorageExpert17 分钟前
DELL SC compellent存储的四种访问方式
运维·服务器·存储维护·emc存储
_GR17 分钟前
每日OJ题_牛客_牛牛冲钻五_模拟_C++_Java
java·数据结构·c++·算法·动态规划
容器( ु⁎ᴗ_ᴗ⁎)ु.。oO18 分钟前
MySQL事务
数据库·mysql
无限大.30 分钟前
c语言200例 067
java·c语言·开发语言
余炜yw32 分钟前
【Java序列化器】Java 中常用序列化器的探索与实践
java·开发语言
攸攸太上32 分钟前
JMeter学习
java·后端·学习·jmeter·微服务
Kenny.志35 分钟前
2、Spring Boot 3.x 集成 Feign
java·spring boot·后端