ClickHouse 配置优化与问题解决

ClickHouse 配置优化与问题解决

一、数据写入优化

使用 RowBinary 格式进行数据入库可显著提升性能,配合异步插入参数效果更佳:

复制代码
async_insert=1
wait_for_async_insert=0
  • async_insert=1:启用异步插入模式,客户端无需等待数据完全写入磁盘即可返回
  • wait_for_async_insert=0:不等待异步插入完成,进一步提高写入吞吐量

RowBinary 格式优势:

  • 二进制存储,体积更小,传输更快
  • 无需进行字符串解析,减少 CPU 消耗
  • 适合大批量数据持续写入场景

二、CPU 配置优化

根据服务器 CPU 情况合理配置线程参数:

xml 复制代码
<background_pool_size>16</background_pool_size>  <!-- 建议设为 CPU 逻辑核数 -->
<concurrent_threads_soft_limit_num>16</concurrent_threads_soft_limit_num>  <!-- 建议设为 CPU 逻辑核数 -->
  • background_pool_size:控制后台任务(如合并、复制)的线程池大小
  • concurrent_threads_soft_limit_num:查询执行的并发线程数软限制

优化原则:

  • 对于 CPU 密集型查询,避免线程数超过逻辑核数导致上下文切换开销
  • 对于 IO 密集型场景,可适当提高线程数利用空闲资源

三、内存使用配置

根据实际内存情况调整以下参数:

xml 复制代码
<max_memory_usage>16GB</max_memory_usage>  <!-- 单个查询的最大内存限制 -->
<max_server_memory_usage_to_ram_ratio>0.8</max_server_memory_usage_to_ram_ratio>  <!-- 总内存使用占系统内存的比例 -->
<max_bytes_before_external_group_by>10GB</max_bytes_before_external_group_by>  <!-- 分组操作溢出到磁盘的阈值 -->

配置建议:

  • max_memory_usage 一般设置为系统内存的 50%-70%
  • max_server_memory_usage_to_ram_ratio 建议不超过 0.8,预留部分内存给系统和其他进程
  • 当内存不足时,max_bytes_before_external_group_by 可触发外部排序,避免查询失败

四、Prometheus 监控配置

通过以下配置启用 Prometheus 监控:

xml 复制代码
<prometheus>
    <endpoint>/metrics</endpoint>
    <port>9363</port>  <!-- 自定义监控端口 -->
    <metrics>true</metrics>  <!-- 启用指标收集 -->
    <events>true</events>  <!-- 启用事件收集 -->
    <asynchronous_metrics>true</asynchronous_metrics>  <!-- 启用异步指标 -->
</prometheus>

监控指标类别:

  • 系统指标:CPU、内存、磁盘 IO 等
  • 数据库指标:连接数、查询速率、插入速率等
  • 表指标:分区数量、数据量、合并次数等

五、JSON 类型支持

如需使用 JSON 类型,需开启实验性特性:

xml 复制代码
<allow_experimental_object_type>1</allow_experimental_object_type>

使用注意事项:

  • 实验性特性可能存在不稳定性
  • JSON 类型查询性能不如结构化字段
  • 适合存储半结构化数据,避免频繁更新

六、密码认证配置

  1. 生成密码哈希:
bash 复制代码
PASSWORD=123456; 
echo "$PASSWORD"; 
echo -n "$PASSWORD" | sha1sum | tr -d '-' | xxd -r -p | sha1sum | tr -d '-'
  1. 配置用户密码:
xml 复制代码
<users>
    <user_name>
        <password_sha256_hex>生成的哈希值</password_sha256_hex>
        <!-- 其他权限配置 -->
    </user_name>
</users>

安全建议:

  • 使用强密码,定期更换
  • 为不同用户分配最小必要权限
  • 结合网络访问控制限制连接来源

七、副本问题解决

  1. 多次查询结果不一致:
xml 复制代码
<load_balancing>first_or_random</load_balancing>
  1. 副本损坏处理:
xml 复制代码
<skip_unavailable_shards>1</skip_unavailable_shards>
  1. 副本表无法删除:
xml 复制代码
<database_atomic_delay_before_drop_table_sec>30</database_atomic_delay_before_drop_table_sec>

调整延迟时间,确保所有副本都完成元数据同步

八、基准测试

使用官方基准测试工具评估性能:

bash 复制代码
git clone https://github.com/ClickHouse/ch-bench.git
cd ch-bench
# 按照文档配置测试环境
./ch-bench.sh

基准测试可评估:

  • 不同数据量下的查询性能
  • 并发查询处理能力
  • 数据加载速度
  • 系统资源利用率

九、常见错误及解决方法

  1. Too many parts 错误

原因:小批量插入过于频繁,导致分区文件过多

解决:

xml 复制代码
<merge_tree>
    <parts_to_delay_insert>600</parts_to_delay_insert>
    <parts_to_throw_insert>600</parts_to_throw_insert>
    <max_delay_to_insert>2</max_delay_to_insert>
    <max_suspicious_broken_parts>5</max_suspicious_broken_parts>
</merge_tree>

同时建议:

  • 提高单次插入数量,降低插入频次
  • 调整 background_pool_size 增加合并线程
  1. java.sql.SQLException: java.io.IOException: Reached end of input stream

原因:连接超时

解决:增加 JDBC 连接超时设置

复制代码
jdbc:clickhouse://xxxx:8123/mydb?socket_timeout=300000
  1. DB::NetException: Connection reset by peer

原因:查询占用内存过大被中断

解决:调整全局内存限制

xml 复制代码
<max_memory_usage_for_all_queries>32GB</max_memory_usage_for_all_queries>
  1. Memory limit (for query) exceeded

原因:单个查询超出内存限制

解决:

xml 复制代码
<max_memory_usage>16GB</max_memory_usage>

或优化 SQL,减少数据处理量

  1. string is too long: length can't exceed maximum length

原因:字符串长度超过限制

解决:调整最大字符串长度

xml 复制代码
<format_binary_max_string_size>104857600</format_binary_max_string_size>  <!-- 100MB -->
相关推荐
数据库生产实战3 小时前
解析Oracle 19C中并行INSERT SELECT的工作原理
数据库·oracle
AAA修煤气灶刘哥4 小时前
服务器指标多到“洪水泛滥”?试试InfluxDB?
数据库·后端·面试
阿沁QWQ5 小时前
MySQL服务器配置与管理
服务器·数据库·mysql
程序新视界6 小时前
MySQL“索引失效”的隐形杀手:隐式类型转换,你了解多少?
数据库·mysql·dba
Logintern096 小时前
windows如何设置mongodb的副本集
数据库·windows·mongodb
RestCloud8 小时前
在制造业数字化转型浪潮中,数据已成为核心生产要素。然而,系统割裂、数据滞后、开发运维成本高等问题,却像顽固的 “数据枷锁”,阻碍着企业发展。ETLCloud与
数据库·postgresql
!chen8 小时前
【Spring Boot】自定义starter
java·数据库·spring boot
十碗饭吃不饱9 小时前
sql报错:java.sql.SQLSyntaxErrorException: Unknown column ‘as0‘ in ‘where clause‘
java·数据库·sql
我是Superman丶9 小时前
【优化】Mysql指定索引查询或忽略某个索引
数据库·mysql