clickhouse生产运维以及调优

集群环境删除表

sql 复制代码
drop table db_name.table_name on cluster default_cluster sync;

集群环境删除字段

sql 复制代码
alter table db_name.table_name on cluster default_cluster drop column `remark`;

删除数据,分异步删除和同步删除

delete,update操作对于ck来说是非常重得操作,ck集群容易卡住。

sql 复制代码
按分区进行删除,该操作异步删除
ALTER TABLE db_name.table_name DROP PARTITION ('37','2021-12-09')

按条件进行删除,该操作同步删除,进行该操作相当于要对表数据重新进行分区处理。
delete操作很慢,可以查询出符合条件的主键id,根据主键id来delete数据。
ALTER TABLE db_name.table_name DELETE WHERE id = 1 and name='小米'

多字段分区或者设置主键得顺序

主键顺序得设置可大幅提高表得查询效率,例如符合主键a,b。如果在业务过程重b作为条件使用较多,那么则在建表遵循最左原则,

ORDER BY (b, a)

clickhouse同步插入数据

sql 复制代码
向分布式表插入同步数据
set insert_distributed_sync = 1; 
插入过程中不设置超时时间
set distributed_ddl_task_timeout = -1;
如果有多个副本,前提是知道集群中有两个副本,只有所有副本同步后采才表名插入成功
set insert_quorum =2;
插入过程中不设置超时时间
set insert_quorum_timeout=3600000;

磁盘清理

sql 复制代码
查看表占用数据得大小
SELECT
    database,
    table,
    formatReadableSize(sum(bytes_on_disk)) AS disk_space,
    sum(bytes_on_disk) AS bytes_on_disk1
FROM system.parts
WHERE (table NOT LIKE '%1111%') AND (table NOT LIKE '%1111%')
GROUP BY
    database,
    table
ORDER BY bytes_on_disk1 DESC;

SELECT
    table,
    formatReadableSize(sum(bytes_on_disk)) AS disk_space,
    sum(bytes_on_disk) AS bytes_on_disk1
FROM system.parts
WHERE database = 'app'
GROUP BY
    table
ORDER BY bytes_on_disk1 DESC limit 10;


truncate table system.query_thread_log;
alter table system.query_thread_log modify TTL event_date + INTERVAL 10 day;
 
 
 
检查数据大小
SELECT table,
       formatReadableSize(sum(data_compressed_bytes)) AS tc,
       formatReadableSize(sum(data_uncompressed_bytes)) AS tu,
       round((sum(data_compressed_bytes) / sum(data_uncompressed_bytes)) * 100,2) AS ratio
  FROM system.columns
 WHERE database = 'app'
 GROUP BY table
 ORDER BY sum(data_compressed_bytes) desc limit 10;
 
  

检查列的大小
SELECT
    column,
    any(type),
    sum(column_data_compressed_bytes) AS compressed,
    sum(column_data_uncompressed_bytes) AS uncompressed,
    sum(rows)
FROM system.parts_columns
WHERE (database = 'app') AND (table = 'app_scrm_yk_member_asset_structure_da_1111') AND active
GROUP BY column
ORDER BY column DESC
LIMIT 10;

clickhouse问题分析

慢查

sql 复制代码
1、字段信息
query_kind:sql执行类型
  select:查询
  insert:插入
type:执行查询时发生的事件类型
  QueryStart,查询执行成功开始
  QueryFinish,查询执行成功结束
  ExceptionBeforeStart,在开始执行查询之前发生异常
  ExceptionWhileProcessing,查询执行期间的异常
event_data:查询开始日期
event_time:查询开始时间
query_start_time:查询开始时间
query_duration_ms:查询执行持续时间
read_rows:读取行数
read_bytes:读取字节数
written_rows:对于插入查询,写入的行数,对于其他查询,值为0
written_bytes:对于插入查询,写入的字节数,对于其他查询,值为0
result_rows:结果中的行数
result_btes:结果中的字节数
memory_usage:查询消耗的内存
query:查询字符串
exception:异常信息
address:发起查询的IP地址
port:发起查询的客户端端口

2、查询一段时间内表写入数据量
SELECT
    sum(if(type = 1, 1, 0)) AS cnt,
    sum(if(type = 2, written_bytes, 0)) AS written_bytes,
    sum(if(type = 2, written_rows, 0)) AS written_rows
FROM clusterAllReplicas('default_cluster', 'system.query_log')
WHERE ((tables[1]) = 'app_eap_event_register_member_de_153579') 
AND (query_kind = 'Insert') AND (event_date = '2023-08-20') 
AND (event_time >= '2023-08-20 21:00:00')
LIMIT 10;

3、查询一段时间内表写入明细
SELECT
    written_bytes,
    written_rows,
    event_time
FROM clusterAllReplicas('default_cluster', 'system.query_log')
WHERE ((tables[1]) = 'app_eap_event_register_member_de_153579') 
AND (query_kind = 'Insert') AND (event_date = '2023-08-20') 
AND (event_time >= '2023-08-20 21:00:00')
LIMIT 10;

4、查询一段时间内表查询明细(根据查询耗时倒叙)
SELECT
    query_kind,
    type,
    event_date,
    event_time,
    read_rows,
    read_bytes,
    result_rows,
    result_bytes,
    query_duration_ms,
    query
FROM clusterAllReplicas('default_cluster', 'system.query_log') AS t
WHERE (query_kind = 'Select') AND (event_date = '2023-08-20') 
AND (event_time >= '2023-08-20 21:00:00')
ORDER BY query_duration_ms DESC
LIMIT 10;

5、查询一段时间内表查询明细(根据结果集倒叙)
SELECT
    query_kind,
    type,
    event_date,
    event_time,
    read_rows,
    read_bytes,
    result_rows,
    result_btes,
    query_duration_ms,
    query
FROM clusterAllReplicas('default_cluster', 'system.query_log') AS t
WHERE (query_kind = 'Select') AND (event_date = '2023-09-26') 
AND (event_time >= '2023-09-26 16:00:00')
ORDER BY result_rows DESC
LIMIT 10;

6、查询一段时间内表查询异常
SELECT
    hostName() AS hostName,
    event_time,
    query,
    query_id,
    exception_code,
    exception,
    stack_trace
FROM clusterAllReplicas('default_cluster', 'system.query_log') AS t
WHERE (query_kind = 'Select') AND (event_date = '2023-09-26') 
AND (event_time >= '2023-09-26 16:00:00') AND (type != 'QueryStart') 
AND (type != 'QueryFinish')
LIMIT 10;

7、查询正在执行的进程
select elapsed,query,query_id from system.processes order by elapsed desc
#KILL QUERY where query_id='query_id';  
#将"query_id"替换为要停止的查询的ID

8、查询待执行的merge
SELECT *
FROM system.mutations
WHERE is_done = 0

#KILL MUTATION WHERE database = 'default' AND table = 'table'
可以终止

耗cpu

sql 复制代码
SELECT
    any(query_duration_ms),
    any(query_start_time),
    any(query),
    sum(`ProfileEvents.Values`[indexOf(`ProfileEvents.Names`, 'UserTimeMicroseconds')]) AS userCPU
FROM system.query_log
WHERE (type = 2) AND (event_date >= today())
GROUP BY normalizedQueryHash(query)
ORDER BY userCPU DESC
LIMIT 10;


#normalizedQueryHash(query) 返回64位的hashID值 不包含相似查询的字面量

查询某个时间内某种查询的数量

sql 复制代码
#将sql聚合
select  normalizedQueryHash(query),count(1) as count
from clusterAllReplicas('default_cluster', 'system.query_log') 
where query_start_time> '2024-03-27 06:00:00' and query_start_time< '2024-03-27 06:55:00'
GROUP BY normalizedQueryHash(query)
order by count desc 
limit 10;
#通过上面得到的SQL hash值查询具体的SQL语句
select query
from clusterAllReplicas('default_cluster', 'system.query_log') 
where query_start_time> '2024-03-27 06:30:00' and query_start_time< '2024-03-27 06:55:00'
and normalizedQueryHash(query)=13758478862166244964 
limit 1;
#或者将以上2句合成1句,但是返回信息太杂乱
select  any(query),normalizedQueryHash(query),count(1) as count
from clusterAllReplicas('default_cluster', 'system.query_log') 
where query_start_time> '2024-03-27 06:00:00' and query_start_time< '2024-03-27 06:55:00'
GROUP BY normalizedQueryHash(query)
order by count desc 
limit 10;

参数优化

clickhouse 设置允许使用窗口函数 set allow_experimental_window_functions = 1

cat /etc/clickhouse-server/users.d/allow_experimental_window_functions.xml

xml 复制代码
<?xml version="1.0"?>
<yandex>
   <profiles>
       <default>
           <allow_experimental_window_functions>1</allow_experimental_window_functions>
       </default>
   </profiles>
</yandex>

ClickHouse 进行复杂查询时,包含多个 left join 和 group by,会报错:超出内存限制。

sql 复制代码
SET max_memory_usage = 128000000000; #128G,
如果没有那么多的内存可用,ClickHouse 可以通过设置这个 "溢出" 数据到磁盘:

set max_bytes_before_external_group_by=20000000000; #20G
set max_memory_usage=40000000000; #40G
将 max_memory_usage 设置为 max_bytes_before_external_group_by 大小的两倍。

如果发现还是报内存不够或者服务器直接崩溃,设置 partial_merge_join = 1,但是运行速度会很慢。

重要系统表

sql 复制代码
执行的sql都可在改表查到
system.query_log

mergeTree表执行的update和delete 
done 1 完成  0 未完成
system.mutations
select * from system.mutations where is_done != '1' order by create_time limit 10;


分布式CREATE, DROP, ALTER, RENAME语句
system.distributed_ddl_queue 
select entry, cluster, query, host_address, port, status,query_start_time from system.distributed_ddl_queue 
where status != '1' order by query_start_time limit 10;


system.processes
正在执行的进程

常见问题解决

ck集群断连

sql 复制代码
阿里云

原因:在2024-01-26 17:40左右,业务高峰期,CPU高达95%(短时间内的CPU高是正常现象),宿主机被打hang住了,阿里云的工程师收到后台告警,第一时间将宿主机重启了。影响时间为:17.45到17.52。
解决:资源打满之后,管控侧的安全策略驱逐了这个节点。这个策略后续后端会优化,后续会有更合理的策略来均衡资源使用。-阿里云侧



在2024-02-19 16:00-16:10左右,又出现底层主机 hang 住了 重启后恢复了
1、对于宿主机问题,这边核实为:ECS 都是单租户模式的,上面只会部署一个用户的实例,负载高一定是实例业务导致的;所以目前迁移底层实例也无法规避这个问题
2、对于优化管控这个问题,因为涉及到底层探活机制的改动,预计3.31之前优化完成。


2024-02-21 14:00 ck集群某个节点发生重启,导致部分查询失败
正常情况如果 SQL需要的内存小于实例可分配的内存,会直接报错不执行,不会导致OOM;

OOM导致重启属于特殊情况:
当内存水位较高(达到了百分之90以上了,持续时间2分左右)

执行的sql的预估内存可能和实际的执行消耗不一样,这可能会由一些缓存或者其他的原因导致,

这个时候也可能出现预估没有超限但是在执行过程中超限的情况。这个时候这个sql在进行内存预估加载mark文件的时候就直接OOM了,

相当于还没预估出来就OOM了。其实这就是所谓的没来得及Kill。

为何避免这种情况,需保证内存水位保持正常状态



2024-05-07
内存高水位,导致集群oom重启了,加一下内存使用率的告警,内存使用率在80%以上就值得注意了,因为操作系统大概会占百分之十几的内存,所以建议您在内存使用率85%设置告警

下面的SQL来查看一下问题时间的大SQL;
select hostname(), formatReadableSize(memory_usage), query_start_time, event_time, query from clusterAllReplicas(default, system.query_log) where event_time >= '2024-05-06 15:25:00' and event_time <= '2024-05-06 15:35:00' order by memory_usage desc LIMIT 100
下面这个SQL可以看问题时间没有执行完成的SQL
WITH '2024-05-06 15:25:00' AS start_time, '2024-05-06 15:35:00' AS end_time SELECT query_id, query FROM system.query_log WHERE event_time BETWEEN start_time AND end_time AND type = 'QueryStart' AND query_id NOT IN ( SELECT query_id FROM system.query_log WHERE event_time BETWEEN start_time AND end_time AND type = 'QueryFinish' )


因为有几条DDL执行太慢卡住了;跟optimize没有直接关系,不过optimize本身也是比较消耗性能的,建议不要下发得过于频繁


华为云
宿主机 认为ck的CPU占用太多 ,把ck kill掉了
关注参数
show settings like 'max_server_memory_usage_to_ram_ratio'; 调低

DDL语句卡住不执行

sql 复制代码
如执行alter delete/update 卡住,卡住会导致后续的所有ddl语句执行不了,卡住第一时间需要解决,否则会影响夜里的任务执行

解决办法:将卡住的zk上队列节点删除掉,再重启ck集群


1、进入zk



2、查到卡住的zk队列节点
ls /clickhouse/distributed_ddl
一般最后一个队列节点就是卡住的队列节点,可以查看该队列节点内容
如get /clickhouse/distributed_ddl/query-0000230088
active finished

或者通过查询system.query_log 可以找到执行卡住的sql的query_id


3、删除卡住的zk队列节点
deleteall /clickhouse/distributed_ddl/query-0000230088


4、重启ck集群,滚动重启的方式,不影响现有业务
相关推荐
心灵彼岸-诗和远方几秒前
DevOps业务价值流:架构设计最佳实践
运维·产品经理·devops
一只哒布刘5 分钟前
NFS服务器
运维·服务器
Ai 编码助手22 分钟前
MySQL中distinct与group by之间的性能进行比较
数据库·mysql
陈燚_重生之又为程序员37 分钟前
基于梧桐数据库的实时数据分析解决方案
数据库·数据挖掘·数据分析
caridle39 分钟前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
白云如幻40 分钟前
MySQL排序查询
数据库·mysql
萧鼎42 分钟前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
^velpro^44 分钟前
数据库连接池的创建
java·开发语言·数据库
苹果醋31 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
荒川之神1 小时前
ORACLE _11G_R2_ASM 常用命令
数据库·oracle