美文网首页
ClickHouse生产问题处理(一)如何去更新字段类型

ClickHouse生产问题处理(一)如何去更新字段类型

作者: 淡淡的小番茄 | 来源:发表于2022-02-10 20:09 被阅读0次

背景

监控发现生产环境kafka的一个topic消费积压:

问题排查

我们是通过kafka引擎表将数据入到clickhouse ods层表中的。本身引擎表的性能是相当可以的,毕竟使用的批量入库,磁盘顺序写。首先怀疑是数据格式非法,导致一直消费不了。查看clickhouse的日志发现如下异常:

2022.02.10 16:43:50.607118 [ 22994 ] {} <Error> void DB::StorageKafka::threadFunc(size_t): Code: 349, e.displayText() = DB::Exception: Cannot convert NULL value to non-Nullable type: while converting source column request_ip to destination column request_ip: while pushing to view xxxx (f4222cc9-2374-4a3e-9937-1a5856204ae8), Stack trace (when copying this message, always include the lines below):

从异常来看,印证了自己的猜测。那么我们来看看如何解决吧?

解决

首先想到的是不是能将ods表中的request_ip字段修改为可空。clickhouse毕竟是olap数据库,不像mysql这样的,我们首先需要了解下clickhouse在这方面的限制及底层处理逻辑。查看官方文档说明如下:

改变列的类型是唯一的复杂型动作 - 它改变了数据文件的内容。对于大型表,执行起来要花费较长的时间。

该操作分为如下处理步骤:

1)为修改的数据准备新的临时文件

2)重命名原来的文件

3)将新的临时文件改名为原来的数据文件名

4)删除原来的文件

仅仅在第一步是耗费时间的。如果该阶段执行失败,那么数据没有变化。如果执行后续的步骤中失败了,数据可以手动恢复。例外的情形是,当原来的文件从文件系统中被删除了,但是新的数据没有写入到临时文件中并且丢失了。

列操作的 ALTER行为是可以被复制的。这些指令会保存在ZooKeeper中,这样每个副本节点都能执行它们。所有的 ALTER 将按相同的顺序执行。

The query waits for the appropriate actions to be completed on the other replicas.

然而,改变可复制表的列是可以被中断的,并且所有动作都以异步方式执行。

ALTER 操作限制

ALTER 操作允许在嵌套的数据结构中创建和删除单独的元素(列),但是不是整个嵌套结构。添加一个嵌套数据结构的列时,你可以用类似这样的名称 name.nested_name 及类型 Array(T) 来操作。嵌套数据结构等同于

列名前带有同样前缀的多个数组列。

不支持对primary key或者sampling key中的列(在 ENGINE 表达式中用到的列)进行删除操作。改变包含在primary key中的列的类型时,如果操作不会导致数据的变化(例如,往Enum中添加一个值,或者将DateTime 类型改成 UInt32),那么这种操作是可行的。

如果 ALTER 操作不足以完成你想要的表变动操作,你可以创建一张新的表,通过 INSERT SELECT将数据拷贝进去,然后通过 RENAME将新的表改成和原有表一样的名称,并删除原有的表。你可以使用 clickhouse-copier 代替 INSERT SELECT。

ALTER 操作会阻塞对表的所有读写操作。换句话说,当一个大的 SELECT 语句和 ALTER同时执行时,ALTER会等待,直到 SELECT 执行结束。与此同时,当 ALTER 运行时,新的 sql 语句将会等待。

对于不存储数据的表(例如 Merge 及 Distributed 表), ALTER 仅仅改变了自身的表结构,不会改变从属的表结构。例如,对 Distributed 表执行 ALTER 操作时,需要对其它包含该表的服务器执行该操作。

https://clickhouse.com/docs/zh/sql-reference/statements/alter/#alter_modify-column

我们这个字段是没有放在主键中的,否则还真是麻烦。修改涉及到ods层两张表,查看了数据量:第一张在20万左右,第二张表数据量已经接近40亿。针对这两张表,我们采用了两种不同方式来处理:

1、小数据量的表,我们直接通过ALTER语句进行类型修改。

2、大数据量的表,我们是直接修改的物化视图,对于空字段增加默认值,使用函数:ifNull(request_ip,'') request_ip。

这样处理后,效果立杆见影:

另外,补充下一个知识点:clickhouse本身是不支持频繁读写的,所以kafka引擎表也使用的批量的方式,来实现数据落盘的。这块你从kafka的topic消费组的监控上就可以看得很清楚:

比较有规律的抖动。批量入库的另外一个问题就是延迟了。

相关文章

网友评论

      本文标题:ClickHouse生产问题处理(一)如何去更新字段类型

      本文链接:https://www.haomeiwen.com/subject/ehkokrtx.html