clickhouse使用问题处理_记录

clickhouse安装部署与问题处理记录

clickhouse安装

安装部分网上资料很多,不再赘述,附上参考文档地址
单机版安装:https://www.jianshu.com/p/fa6bf0a4a903
集群安装:以下两种方式都是三分片两副本的方式
6节点安装教程:https://blog.youkuaiyun.com/lusklusklusk/article/details/134741272
3节点安装教程:https://blog.youkuaiyun.com/qq_36933421/article/details/128283423
注意:clickhouse集群安装最佳实践是分片数*副本数=实例数,因此,3节点部署实际是在一个节点上起了2个实例,6节点部署则是一个节点起一个实例

使用问题处理记录

Code: 241. DB::Exception: Memory limit (total) exceeded: would use 6.32 GiB (attempt to allocate chunk of 4360416 bytes), maximum: 6.27 GiB. OvercommitTracker decision: Query was selected to stop by OvercommitTracker. (MEMORY_LIMIT_EXCEEDED) (version 23.8.8.20 (official build))

java.sql.BatchUpdateException: Code: 241. DB::Exception: Memory limit (total) exceeded: would use 6.32 GiB (attempt to allocate chunk of 4360416 bytes), maximum: 6.27 GiB. OvercommitTracker decision: Query was selected to stop by OvercommitTracker. (MEMORY_LIMIT_EXCEEDED) (version 23.8.8.20 (official build))
, server ClickHouseNode [uri=http://10.127.228.145:18123/default, options={compress=0,use_time_zone=Asia/Shanghai,use_server_time_zone=false}]@-236135211
at com.clickhouse.jdbc.SqlExceptionUtils.batchUpdateError(SqlExceptionUtils.java:107)
at com.clickhouse.jdbc.internal.InputBasedPreparedStatement.executeAny(InputBasedPreparedStatement.java:154)
at com.clickhouse.jdbc.internal.AbstractPreparedStatement.executeLargeBatch(AbstractPreparedStatement.java:85)
at com.clickhouse.jdbc.internal.ClickHouseStatementImpl.executeBatch(ClickHouseStatementImpl.java:752)
at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils . s a v e P a r t i t i o n ( J d b c U t i l s . s c a l a : 667 ) a t o r g . a p a c h e . s p a r k . s q l . e x e c u t i o n . d a t a s o u r c e s . j d b c . J d b c U t i l s .savePartition(JdbcUtils.scala:667) at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils .savePartition(JdbcUtils.scala:667)atorg.apache.spark.sql.execution.datasources.jdbc.JdbcUtils a n o n f u n anonfun anonfunsaveTable 1. a p p l y ( J d b c U t i l s . s c a l a : 834 ) a t o r g . a p a c h e . s p a r k . s q l . e x e c u t i o n . d a t a s o u r c e s . j d b c . J d b c U t i l s 1.apply(JdbcUtils.scala:834) at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils 1.apply(JdbcUtils.scala:834)atorg.apache.spark.sql.execution.datasources.jdbc.JdbcUtils a n o n f u n anonfun anonfunsaveTable 1. a p p l y ( J d b c U t i l s . s c a l a : 834 ) a t o r g . a p a c h e . s p a r k . r d d . R D D 1.apply(JdbcUtils.scala:834) at org.apache.spark.rdd.RDD 1.apply(JdbcUtils.scala:834)atorg.apache.spark.rdd.RDD a n o n f u n anonfun anonfunforeachPartition 1 1 1 a n o n f u n anonfun anonfunapply 28. a p p l y ( R D D . s c a l a : 935 ) a t o r g . a p a c h e . s p a r k . r d d . R D D 28.apply(RDD.scala:935) at org.apache.spark.rdd.RDD 28.apply(RDD.scala:935)atorg.apache.spark.rdd.RDD a n o n f u n anonfun anonfunforeachPartition 1 1 1 a n o n f u n anonfun anonfunapply 28. a p p l y ( R D D . s c a l a : 935 ) a t o r g . a p a c h e . s p a r k . S p a r k C o n t e x t 28.apply(RDD.scala:935) at org.apache.spark.SparkContext 28.apply(RDD.scala:935)atorg.apache.spark.SparkContext a n o n f u n anonfun anonfunrunJob 5. a p p l y ( S p a r k C o n t e x t . s c a l a : 2121 ) a t o r g . a p a c h e . s p a r k . S p a r k C o n t e x t 5.apply(SparkContext.scala:2121) at org.apache.spark.SparkContext 5.apply(SparkContext.scala:2121)atorg.apache.spark.SparkContext a n o n f u n anonfun anonfunrunJob 5. a p p l y ( S p a r k C o n t e x t . s c a l a : 2121 ) a t o r g . a p a c h e . s p a r k . s c h e d u l e r . R e s u l t T a s k . r u n T a s k ( R e s u l t T a s k . s c a l a : 90 ) a t o r g . a p a c h e . s p a r k . s c h e d u l e r . T a s k . r u n ( T a s k . s c a l a : 121 ) a t o r g . a p a c h e . s p a r k . e x e c u t o r . E x e c u t o r 5.apply(SparkContext.scala:2121) at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:90) at org.apache.spark.scheduler.Task.run(Task.scala:121) at org.apache.spark.executor.Executor 5.apply(SparkContext.scala:2121)atorg.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:90)atorg.apache.spark.scheduler.Task.run(Task.scala:121)atorg.apache.spark.executor.ExecutorTaskRunner$$anonfun 11. a p p l y ( E x e c u t o r . s c a l a : 407 ) a t o r g . a p a c h e . s p a r k . u t i l . U t i l s 11.apply(Executor.scala:407) at org.apache.spark.util.Utils 11.apply(Executor.scala:407)atorg.apache.spark.util.Utils.tryWithSafeFinally(Utils.scala:1408)
at org.apache.spark.executor.Executor T a s k R u n n e r . r u n ( E x e c u t o r . s c a l a : 413 ) a t j a v a . u t i l . c o n c u r r e n t . T h r e a d P o o l E x e c u t o r . r u n W o r k e r ( T h r e a d P o o l E x e c u t o r . j a v a : 1149 ) a t j a v a . u t i l . c o n c u r r e n t . T h r e a d P o o l E x e c u t o r TaskRunner.run(Executor.scala:413) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor TaskRunner.run(Executor.scala:413)atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)atjava.util.concurrent.ThreadPoolExecutorWorker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

集群环境:3节点,4C8G,centos7
数据情况:kafka数据,少量数据,字段数据在4K以上
处理方式:
方式一

减少字段数量,参考资料:https://www.bilibili.com/read/cv17502956/

方式二

修改clickhouse配置 /etc/clickhouse-server/config.xml
设置 max_server_memory_usage_to_ram_ratio 在机器内存小的情况下,可将此值设置的大于1
设置 max_server_memory_usage 为0
在这里插入图片描述
修改clickhouse配置 /etc/clickhouse-server/users.xml
修改profile中的配置,设置 <max_memory_usage> 128000000000</max_memory_usage> #128G,
如果没有那么多的内存可用,ClickHouse可以通过设置这个“溢出”数据到磁盘:
<max_bytes_before_external_group_by>20000000000</max_bytes_before_external_group_by>; #20G
<max_memory_usage>40000000000</max_memory_usage>; #40G
将max_memory_usage设置为max_bytes_before_external_group_by大小的两倍。
个人理解clickhouse会先申请内存,如果申请不到,就会报错退出;虽然申请的内存超过了本机内存大小,但是实际上,由于数据量可能不是那么多,因此在实际使用时,并没有用到那么大的内存,因此,可以将以上值设置的大一点。
参考资料:https://clickhouse.com/docs/en/operations/server-configuration-parameters/settings

持续更新中,遇到问题再增加。。。

### ClickHouse MEMORY_LIMIT_EXCEEDED 报错的原因及解决方案 #### 原因分析 ClickHouse 中 `MEMORY_LIMIT_EXCEEDED` 错误通常发生在查询过程中使用的内存超过了设定的最大限制。默认情况下,ClickHouse 对单个查询的内存使用上限设置为 10 GiB[^1]。如果某个查询尝试分配超过此限制的内存,则会触发该错误。 这种问题可能由以下几个因素引起: 1. **大数据集处理**:当查询涉及大量数据(如扫描近200M行的数据),可能会消耗较多内存资源。 2. **复杂计算操作**:某些聚合函数(如 `uniqExact`)或复杂的 JOIN 和 GROUP BY 操作可能导致更高的内存需求。 3. **不合理的配置参数**:例如未调整 `max_memory_usage` 或其他相关参数,使得系统无法适应高负载场景下的内存需求。 --- #### 解决方案 ##### 方法一:增加最大允许内存限制 可以通过修改 ClickHouse 配置文件中的 `max_memory_usage` 参数来提升单次查询可使用的最大内存量。具体做法是在配置文件中添加或更改以下字段: ```xml <profiles> <default> <!-- 设置新的内存限制 --> <max_memory_usage>20000000000</max_memory_usage> <!-- 单位字节, 此处设为20GB --> </default> </profiles> ``` 或者通过 SQL 动态调整当前 session 的内存限制: ```sql SET max_memory_usage = &#39;20Gi&#39;; ``` 这种方法适用于临时需要更高内存支持的情况,但需谨慎评估硬件条件以防止 OOM (Out of Memory)。 ##### 方法二:优化查询逻辑 重新设计查询语句可以显著降低其对内存的需求。以下是几种常见的优化手段: - 替换耗内存较高的聚合函数;比如用更高效的近似算法代替精确去重(`uniqExact`)。 - 减少中间结果大小——利用过滤器提前排除不必要的记录。 对于大规模数据集合上的运算尤其重要的是考虑分步执行策略而不是一次性加载整个数据集到内存里完成所有工作流。 ##### 方法三:启用分布式模式或多节点部署 如果单一服务器难以满足高性能需求,那么构建集群环境将是另一个可行的选择。借助副本机制(replication),不仅可以提高可用性和容灾能力,还能分散读写压力从而缓解局部资源紧张状况[^2]。 另外,在多台机器上平行运行相同任务也可以有效分割原始问题规模进而减少个体负担。 ##### 方法四:合理应用采样技术 针对那些不需要绝对精准统计的应用场合来说,采用样本估算往往能带来事半功倍的效果。MergeTree引擎家族成员本身就具备良好的原生支持特性,只需定义好相应的抽样表达式即可开启这项功能[^3]。 最后值得注意的一点是网络层面超时控制同样不容忽视,适当延长连接等待时限有助于避免因为短暂延迟而导致失败中断现象发生[^4]。 --- ### 总结 综上所述,面对 ClickHouse 查询过程中可能出现的 `MEMORY_LIMIT_EXCEEDED` 异常情况,可以从多个角度出发寻找对应措施加以应对。无论是直接扩大物理容量边界还是深入挖掘业务特点寻求替代路径都值得探索实践一番。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值