14|跳数索引:后起新秀ClickHouse

你好,我是徐长龙。

通过前面的学习,我们见识到了Elasticsearch的强大功能。不过在技术选型的时候,价格也是重要影响因素。Elasticsearch虽然用起来方便,但却有大量的硬件资源损耗,再富有的公司,看到每月服务器账单的时候也会心疼一下。

而ClickHouse是新生代的OLAP,尝试使用了很多有趣的实现,虽然仍旧有很多不足,比如不支持数据更新、动态索引较差、查询优化难度高、分布式需要手动设计等问题。但由于它架构简单,整体相对廉价,逐渐得到很多团队的认同,很多互联网企业加入社区,不断改进ClickHouse。

ClickHouse属于列式存储数据库,多用于写多读少的场景,它提供了灵活的分布式存储引擎,还有分片、集群等多种模式,供我们搭建的时候按需选择。

这节课我会从写入、分片、索引、查询的实现这几个方面带你重新认识ClickHouse。在学习过程中建议你对比一下Elasticsearch、MySQL、RocksDB的具体实现,想想它们各有什么优缺点,适合什么样的场景。相信通过对比,你会有更多收获。

并行能力CPU吞吐和性能

我先说说真正使用ClickHouse的时候,最让我意料不到的地方。

我们先选个熟悉的参照物——MySQL,MySQL在处理一个SQL请求时只能利用一个CPU。但是ClickHouse则会充分利用多核,对本地大量数据做快速的计算,因此ClickHouse有更高的数据处理能力(2~30G/s,未压缩数据),但是这也导致它的并发不高,因为一个请求就可以用光所有系统资源。

我们刚使用ClickHouse的时候,常常碰到查几年的用户行为时,一个SQL就会将整个ClickHouse卡住,几分钟都没有响应的情况。

官方建议ClickHouse的查询QPS 限制在100左右,如果我们的查询索引设置得好,几十上百亿的数据可以在1秒内将数据统计返回。作为参考,如果换成MySQL,这个时间至少需要一分钟以上;而如果ClickHouse的查询设计得不好,可能等半小时还没有计算完毕,甚至会出现卡死的现象。

所以,你使用ClickHouse的场景如果是对用户服务的,最好对这种查询做缓存。而且,界面在加载时要设置30秒以上的等待时间,因为我们的请求可能在排队等待别的查询。

如果我们的用户量很大,建议多放一些节点用分区、副本、相同数据子集群来分担查询计算的压力。不过,考虑到如果想提供1w QPS查询,极端的情况下需要100台ClickHouse存储同样的数据,所以建议还是尽量用脚本推送数据结果到缓存中对外服务。

但是,如果我们的集群都是小数据,并且能够保证每次查询都可控,ClickHouse能够支持每秒上万QPS的查询,这取决于我们投入多少时间去做优化分析。

对此,我推荐的优化思路是:基于排序字段做范围查询过滤后,再做聚合查询。你还要注意,需要高并发查询数据的服务和缓慢查询的服务需要隔离开,这样才能提供更好的性能。

分享了使用体验,我们还是按部就班来分析分析ClickHouse在写入、储存、查询等方面的特性,这样你才能更加全面深入地认识它。

批量写入优化

ClickHouse的客户端驱动很有意思,客户端会有多个写入数据缓存,当我们批量插入数据时,客户端会将我们要insert的数据先在本地缓存一段时间,直到积累足够配置的block_size后才会把数据批量提交到服务端,以此提高写入的性能。

如果我们对实时性要求很高的话,这个block_size可以设置得小一点,当然这个代价就是性能变差一些。

为优化高并发写服务,除了客户端做的合并,ClickHouse的引擎MergeTree也做了类似的工作。为此单个ClickHouse批量写性能能够达到280M/s(受硬件性能及输入数据量影响)。

MergeTree采用了批量写入磁盘、定期合并方式(batch write-merge),这个设计让我们想起写性能极强的RocksDB。其实,ClickHouse刚出来的时候,并没有使用内存进行缓存,而是直接写入磁盘。

最近两年ClickHouse做了更新,才实现了类似内存缓存及WAL日志。所以,如果你使用ClickHouse,建议你搭配使用高性能SSD作为写入磁盘存储。

事实上,OLAP有两种不同数据来源:一个是业务系统,一个是大数据。

来自业务系统的数据,属性字段比较多,但平时更新量并不大。这种情况下,使用ClickHouse常常是为了做历史数据的筛选和属性共性的计算。而来自大数据的数据通常会有很多列,每个列代表不同用户行为,数据量普遍会很大。

两种情况数据量不同,那优化方式自然也不同,具体ClickHouse是怎么对这这两种方式做优化的呢?我们结合后面的图片继续分析:

图片

当我们批量输入的数据量小于min_bytes_for_wide_part设置时,会按compact part方式落盘。这种方式会将落盘的数据放到一个data.bin文件中,merge时会有很好的写效率,这种方式适合于小量业务数据筛选使用。

当我们批量输入的数据量超过了配置规定的大小时,会按wide part方式落盘,落盘数据的时候会按字段生成不同的文件。这个方式适用于字段较多的数据,merge相对会慢一些,但是对于指定参与计算列的统计计算,并行吞吐写入和计算能力会更强,适合分析指定小范围的列计算。

可以看到,这两种方式对数据的存储和查询很有针对性,可见字段的多少、每次的更新数据量、统计查询时参与的列个数,这些因素都会影响到我们服务的效率。

当我们大部分数据都是小数据的时候,一条数据拆分成多个列有一些浪费磁盘IO,因为是小量数据,我们也不会给他太多机器,这种情况推荐使用compact parts方式。当我们的数据列很大,需要对某几个列做数据统计分析时,wide part的列存储更有优势。

ClickHouse如何提高查询效率

可以看到,数据库的存储和数据如何使用、如何查询息息相关。不过,这种定期落盘的操作虽然有很好的写性能,却产生了大量的data part文件,这会对查询效率很有影响。那么ClickHouse是如何提高查询效率呢?

我们再仔细分析下,新写入的parts数据保存在了 data parts 文件夹内,数据一旦写入数据内容,就不会再进行更改。

一般来说,data part的文件夹名格式为 partition(分区)_min_block_max_block_level,并且为了提高查询效率,ClickHouse会对data part定期做merge合并。

图片

如上图所示,merge操作会分层进行,期间会减少要扫描的文件夹个数,对数据进行整理、删除、合并操作。你还需要注意,不同分区无法合并,所以如果我们想提高一个表的写性能,多分几个分区会有帮助。

如果写入数据量太大,而且数据写入速度太快,产生文件夹的速度会超过后台合并的速度,这时ClickHouse就会报Too many part错误,毕竟data parts文件夹的个数不能无限增加。

面对这种报错,调整min_bytes_for_wide_part或者增加分区都会有改善。如果写入数据量并不大,你可以考虑多生成compact parts数据,这样可以加快合并速度。

此外,因为分布式的ClickHouse表是基于ZooKeeper做分布式调度的,所以表数据一旦写并发过高,ZooKeeper就会成为瓶颈。遇到类似问题,建议你升级ClickHouse,新版本支持多组ZooKeeper,不过这也意味着我们要投入更多资源。

稀疏索引与跳数索引

ClickHouse的查询功能离不开索引支持。Clickhouse有两种索引方式,一种是主键索引,这个是在建表时就需要指定的;另一种是跳表索引,用来跳过一些数据。这里我更推荐我们的查询使用主键索引来查询。

主键索引

ClickHouse的表使用主键索引,才能让数据查询有更好的性能,这是因为数据和索引会按主键进行排序存储,用主键索引查询数据可以很快地处理数据并返回结果。ClickHouse属于“左前缀查询”——通过索引和分区先快速缩小数据范围,然后再遍历计算,只不过遍历计算是多节点、多CPU并行处理的。

那么ClickHouse如何进行数据检索?这需要我们先了解下data parts文件夹内的主要数据组成,如下图:

图片

结合图示,我们按从大到小的顺序看看data part的目录结构。

在data parts文件夹中,bin文件里保存了一个或多个字段的数据。继续拆分bin文件,它里面是多个block数据块,block是磁盘交互读取的最小单元,它的大小取决于min_compress_block_size设置。

我们继续看block内的结构,它保存了多个granule(颗粒),这是数据扫描的最小单位。每个granule默认会保存8192行数据,其中第一条数据就是主键索引数据。data part文件夹内的主键索引,保存了排序后的所有主键索引数据,而排序顺序是创建表时就指定好的。

为了加快查询的速度,data parts内的主键索引(即稀疏索引)会被加载在内存中,并且为了配合快速查找数据在磁盘的位置,ClickHouse在data part文件夹中,会保存多个按字段名命名的mark文件,这个文件保存的是bin文件中压缩后的block的offset,以及granularity在解压后block中的offset,整体查询效果如下图:

图片

具体查询过程是这样的,我们先用二分法查找内存里的主键索引,定位到特定的mark文件,再根据mark查找到对应的block,将其加载到内存,之后在block里找到指定的granule开始遍历加工,直到查到需要的数据。

同时由于ClickHouse允许同一个主键多次Insert的,查询出的数据可能会出现同一个主键数据出现多次的情况,需要我们人工对查询后的结果做去重。

跳数索引

你可能已经发现了,ClickHouse除了主键外,没有其他的索引了。这导致无法用主键索引的查询统计,需要扫全表才能计算,但数据库通常每天会保存几十到几百亿的数据,这么做性能就很差了。

因此在性能抉择中,ClickHouse通过反向的思维,设计了跳数索引来减少遍历granule的资源浪费,常见的方式如下:

  • min_max:辅助数字字段范围查询,保存当前矩阵内最大最小数;
  • set:可以理解为列出字段内所有出现的枚举值,可以设置取多少条;
  • Bloom Filter:使用Bloom Filter确认数据有没有可能在当前块;
  • func:支持很多where条件内的函数,具体你可以查看 官网

跳数索引会按上面提到的类型和对应字段,保存在data parts文件夹内,跳数索引并不是减少数据搜索范围,而是排除掉不符合筛选条件的granule,以此加快我们查询速度。

好,我们回头来整体看看ClickHouse的查询工作流程:

1.根据查询条件,查询过滤出需要读取的data part 文件夹范围;

2.根据data part 内数据的主键索引、过滤出要查询的granule;

3.使用skip index 跳过不符合的granule;

4.范围内数据进行计算、汇总、统计、筛选、排序;

5.返回结果。

我补充说明一下,上面这五步里,只有第四步里的几个操作是并行的,其他流程都是串行。

在实际用上ClickHouse之后,你会发现很难对它做索引查询优化,动不动就扫全表,这是为什么呢?

主要是我们大部分数据的特征不是很明显、建立的索引区分度不够。这导致我们写入的数据,在每个颗粒内区分度不大,通过稀疏索引的索引无法排除掉大多数的颗粒,所以最终ClickHouse只能扫描全表进行计算。

另一方面,因为目录过多,有多份数据同时散落在多个data parts文件夹内,ClickHouse需要加载所有date part的索引挨个查询,这也消耗了很多的资源。这两个原因导致ClickHouse很难做查询优化,当然如果我们的输入数据很有特征,并且特征数据插入时,能够按特征排序顺序插入,性能可能会更好一些。

实时统计

前面我们说了ClickHouse往往要扫全表才做统计,这导致它的指标分析功能也不是很友好,为此官方提供了另一个引擎,我们来看看具体情况。

类似我们之前讲过的内存计算,ClickHouse能够将自己的表作为数据源,再创建一个Materialized View的表,View表会将数据源的数据通过聚合函数实时统计计算,每次我们查询这个表,就能获得表规定的统计结果。

下面我给你举个简单例子,看看它是如何使用的:

-- 创建数据源表
CREATE TABLE products_orders
(
    prod_id    UInt32 COMMENT '商品',
    type       UInt16 COMMENT '商品类型',
    name       String COMMENT '商品名称',
    price     Decimal32(2) COMMENT '价格'
) ENGINE = MergeTree() 
ORDER BY (prod_id, type, name) 
PARTITION BY prod_id;

--创建 物化视图表
CREATE MATERIALIZED VIEW product_total
ENGINE = AggregatingMergeTree() 
PARTITION BY prod_id 
ORDER BY (prod_id, type, name) 
AS
SELECT prod_id, type, name, sumState(price) AS price
FROM products_orders
GROUP BY prod_id, type, name;

-- 插入数据
INSERT INTO products_orders VALUES 
(1,1,'过山车玩具', 20000),
(2,2,'火箭',10000);

-- 查询结果
SELECT prod_id,type,name,sumMerge(price) 
FROM product_total 
GROUP BY prod_id, type, name;

当数据源插入ClickHouse数据源表,生成data parts数据时,就会触发View表。View表会按我们创建时设置的聚合函数,对插入的数据做批量的聚合。每批数据都会生成一条具体的聚合统计结果并写入磁盘。

当我们查询统计数据时,ClickHouse会对这些数据再次聚合汇总,才能拿到最终结果对外做展示。这样就实现了指标统计,这个实现方式很符合ClickHouse的引擎思路,这很有特色。

分布式表

最后,我额外分享一个ClicHouse的新特性。不过这部分实现还不成熟,所以我们把重点放在这个特性支持什么功能上。

ClickHouse的分布式表,不像Elasticsearch那样全智能地帮我们分片调度,而是需要研发手动设置创建,虽然官方也提供了分布式自动创建表和分布式表的语法,但我不是很推荐,因为资源的调配目前还是偏向于人工规划,ClickHouse并不会自动规划,使用类似的命令会导致100台服务器创建100个分片,这有些浪费。

使用分布式表,我们就需要先在不同服务器手动创建相同结构的分片表,同时在每个服务器创建分布式表映射,这样在每个服务上都能访问这个分布式表。

我们通常理解的分片是同一个服务器可以存储多个分片,而ClickHouse并不一样,它规定一个表在一个服务器里只能存在一个分片。

ClickHouse的分布式表的数据插入,一般有两种方式。

一种是对分布式表插入数据,这样数据会先在本地保存,然后异步转发到对应分片,通过这个方式实现数据的分发存储。

第二种是由客户端根据不同规则(如随机、hash),将分片数据推送到对应的服务器上。这样相对来说性能更好,但是这么做,客户端需要知道所有分片节点的IP。显然,这种方式不利于失败恢复。

为了更好平衡高可用和性能,还是推荐你选择前一种方式。但是由于各个分片为了保证高可用,会先在本地存储一份,然后再同步推送,这很浪费资源。面对这种情况,我们比较推荐的方式是通过类似proxy服务转发一层,用这种方式解决节点变更及直连分发问题。

我们再说说主从分片的事儿。ClickHouse的表是按表设置副本(主从同步),副本之间支持同步更新或异步同步。

主从分片通过分布式表设置在ZooKeeper内的相同路径来实现同步,这种设置方式导致ClickHouse的分片和复制有很多种组合方式,比如:一个集群内多个子集群、一个集群整体多个分片、客户端自行分片写入数据、分布式表代理转发写入数据等多种方式组合。

简单来说,就是ClickHouse支持人为做资源共享的多租户数据服务。当我们扩容服务器时,需要手动修改新加入集群分片,创建分布式表及本地表,这样的配置才可以实现数据扩容,但是这种扩容数据不会自动迁移。

总结

ClickHouse作为OLAP的新秀代表,拥有很多独特的设计,它引起了OLAP数据库的革命,也引发很多云厂商做出更多思考,参考它的思路来实现HTAP服务。

通过今天的讲解,相信你也明白ClickHouse的关键特性了。

我们来回顾一下:ClickHouse通过分片及内存周期顺序落盘,提高了写并发能力;通过后台定期合并data parts文件,提高了查询效率;在索引方面,通过稀疏索引缩小了检索数据的颗粒范围,对于不在主键的查询,则是通过跳数索引来减少遍历数据的数据量;另外,ClickHouse还有多线程并行读取筛选的设计。

这些特性,共同实现了ClickHouse大吞吐的数据查找功能。

而最近选择 Elasticsearch还是ClickHouse更好的话题,讨论得非常火热,目前来看还没有彻底分出高下。

个人建议如果硬件资源丰富,研发人员少的话,就选择Elasticsearch;硬件资源少,研发人员多的情况,可以考虑试用ClickHouse;如果硬件和人员都少,建议买云服务的云分布式数据库去做,需要根据团队具体情况来合理地决策。

我还特意为你整理了一张评估表格,贴在了文稿里。

图片

思考题

ClickHouse是不能轻易修改删除数据的,那我们要如何做历史数据的清理呢?

期待你在留言区与我互动交流!如果觉得这节课内容还不错,请推荐、分享给更多朋友。

精选留言

  • 黄堃健

    2024-03-09 10:41:21

    好,我们回头来整体看看 ClickHouse 的查询工作流程:
    1. 根据查询条件,查询过滤出需要读取的 data part 文件夹范围;
    2. 根据 data part 内数据的主键索引、过滤出要查询的 granule;
    3. 使用 skip index 跳过不符合的 granule;

    -- 老师, 前面的3个步骤都涉及到过滤,不明白有什么区别,能举例说明一下吗?
    作者回复

    你好,堃健,在 ClickHouse 的查询工作流程中,前三个步骤虽然都涉及到过滤,但它们各自的目的和操作方式有所不同。下面我将通过举例来解释这三个步骤的区别:

    1. 根据查询条件,查询过滤出需要读取的 data part 文件夹范围
    这个步骤主要是通过分区键(如果有的话)来快速定位到需要查询的数据所在的 data part 文件夹。由于 ClickHouse 支持分区,每个分区可以包含多个 data part,这一步可以大大减少查询需要处理的数据量。

    举例:假设你有一个销售数据表,按月份分区。如果你想要查询2023年1月份的所有销售记录,那么这一步就会直接定位到2023年1月的分区,而忽略其他月份的数据。

    2. 根据 data part 内数据的主键索引、过滤出要查询的 granule
    在这个步骤中,ClickHouse 会使用主键索引来进一步缩小查询范围到特定的 granule。主键索引允许 ClickHouse 快速定位到数据所在的 block。

    举例:在同一个销售数据表中,假设主键是 order_id。如果你要查询 order_id 等于 12345 的记录,ClickHouse 会通过主键索引快速找到包含这个 order_id 的 granule。

    3. 使用 skip index 跳过不符合的 granule
    跳数索引(skip index)的作用是在查询过程中排除那些肯定不包含符合条件数据的 granule,从而减少不必要的磁盘 I/O。

    举例:假设你的查询条件是 price > 100,并且你在 price 字段上建立了 min_max 跳数索引。在查询时,如果某个 granule 的价格范围(通过 min_max 索引得知)完全低于100,那么 ClickHouse 就会跳过这个 granule,不对其进行读取。

    总结一下,这三个步骤可以这样理解:

    第一步是宏观上的数据过滤,通过分区键快速定位到数据所在的 data part。
    第二步是中观上的数据过滤,通过主键索引定位到具体的 granule。
    第三步是微观上的数据过滤,通过跳数索引跳过不可能包含符合条件数据的 granule,以减少查询所需资源。
    在实际使用中,这些步骤共同作用,使得 ClickHouse 能够高效地进行大数据量的查询。

    2024-03-11 10:55:02

  • lvvp

    2024-09-04 21:06:42

    为什么是写多于读?olap场景,读多写少(强调大批量一次性写入增加吞吐量)
  • 黄堃健

    2024-03-09 10:46:12

    在实际用上 ClickHouse 之后,你会发现很难对它做索引查询优化,动不动就扫全表,这是为什么呢?
    主要是我们大部分数据的特征不是很明显、建立的索引区分度不够高

    --老师,索引区分度不够高。 这个索引区分度 指的是 主键索引,还是跳表索引。

    谢谢老师的评论。
    作者回复

    你好,堃健,索引区分度通常指的是主键索引和跳表索引的有效性。在 ClickHouse 中,主键索引是建表时指定的,它能够帮助快速定位到特定的数据颗粒(granule)。而跳表索引(也称为稀疏索引)是一种辅助索引,它可以帮助查询时跳过不符合条件的数据块。

    在问题中,提到的“索引区分度不够高”可能指的是这两种索引中的任何一种或两者的结合。具体来说:

    主键索引区分度:如果主键索引的选择不够具有区分度,即索引字段的数据分布比较均匀或者重复性较高,那么在查询时,ClickHouse 可能需要扫描更多的颗粒来找到匹配的数据,这会导致查询效率降低。

    跳表索引区分度:跳表索引是为了减少查询时需要扫描的数据量。如果跳表索引的区分度不够高,即索引无法有效地排除大量的不符合条件的数据颗粒,查询优化器可能会选择扫描全表,因为使用索引带来的额外开销可能比全表扫描还要大。

    因此,当提到“索引区分度不够高”时,它可能指的是在 ClickHouse 中建立的主键索引和/或跳表索引不足以有效地减少查询需要处理的数据量。为了优化这种情况,可以考虑以下措施:

    优化主键选择:选择更有区分度的字段作为主键,以便在查询时能够更快地定位到数据颗粒。
    使用辅助索引:在适当的字段上创建跳表索引,以帮助查询时跳过不符合条件的数据块。
    调整数据模型:如果可能,重新组织数据模型,以便数据插入时能够按照有区分度的特征排序,这样可以提高索引的效率。

    2024-03-11 10:56:51

  • 黄堃健

    2024-02-20 21:40:42

    老师,新年好, 大部分数据的特征不是很明显、建立的索引区分度不够? 这句话怎么理解?是主键的区分度不高吗? 因为只有主键才有索引。如果是主键,怎么可能区分度不高呢? 如果不是?究竟是怎么意思?
    作者回复

    你好,堃健,说这一句是因为我们很多数据结构在后期都会碰到和我们开始设计相违背的查询,所以ck这种只有建表索引的库后期很多查询基本都是遍历,这对我们toC的场景不友好,并且ck主键还承担了(mergtree)合并去重功能,所以导致用他多数用于OLAP统计count场景,toC业务使用成本太高。而数据特征不明显这里特指当我们的数据超过一定数量后很难用一些属性大量筛选缩小遍历数据范围,综合起来只有一个建表的索引就会有一些不够,虽然最后还有跳数索引,但是这个索引只是降低cpu和io消耗

    2024-02-22 08:18:09

  • IT小村

    2023-12-02 17:13:05

    elasticsearch的写性能并不高
    作者回复

    你好,可以尝试使用Rally对es集群进行测试分析,增加分片服务器会提高写性能,多加几台对比即可。

    2023-12-06 13:53:47

  • zhou

    2023-02-07 08:25:52

    clickhourse存储有leve0,leve1,leve2,用datapart的文件的方式存储,那多节点的情况下是如何做到同步的。
    作者回复

    clickhouse的副本是使用zk做的同步通知,当写入方更新后 本地会写对应目录下的操作日志文件,并且会同步更新zk对应路径下的offset。这时订阅方会watch到这个变更后,会主动去对应的地方下载操作日志,并更新自己的zk记录的同步offset

    2023-02-09 10:07:23

  • 林龍

    2023-01-11 22:23:17

    读吞吐跟QPS有什么区别?一直以为是同个东西
    作者回复

    你好,林龍,吞吐能力一般指数据量,比如一秒能写600Mb数据,一秒能读取200Mb数据,QPS是每秒能处理多少请求。

    2023-01-12 14:22:50

  • 林龍

    2023-01-11 22:21:41

    感觉用clickhouse就是为了解决MySQL慢的问题,但是却没有es那么好用,还要考虑的问题反而加大了
    作者回复

    你好,林龍,clickhouse是解决了实时大量计算数据问题,他的QPS并不高,偶尔还会因为错误查询姿势导致服务卡死。使用OLAP主要还是因为大数据的离线计算很缓慢,有时候几百台的大数据服务器集群全量计算20个大任务需要一天时间,而OLAP期望是在一分钟以内,OLAP他主要功能是在加工清理统计过后的大量历史数据中实时计算统计数据返回给图表系统或业务系统使用。所以其实他不是替代MySQL,毕竟MySQL一般都是对外提供业务服务,这很在意响应速度的,普遍希望1秒内返回,对响应速度要求更高。

    2023-01-12 14:29:08

  • 分清云淡

    2022-12-14 10:35:08

    mysql写性能不差吧?
    作者回复

    你好,分清云淡,核心在于主库只有一个,无法通过增加服务器线性提升写性能。

    2022-12-14 16:49:11

  • Layne

    2022-12-05 09:34:41

    看到了几个通性:
    1.利用分片提高写性能
    2.通过后期合并来提高查询性能
    3.利用布隆过滤器快速检验数据存在标志位
    4.利用顺序性特性,磁盘顺序写,存储文件顺序性,天生降低数据的杂乱
    作者回复

    没毛病

    2022-12-05 12:53:54

  • Elvis Lee

    2022-11-24 11:40:19

    ClickHouse 是不能轻易修改删除数据的,那我们要如何做历史数据的清理呢?
    1.设置TTL
    2.表使用ReplaceMergetree
    作者回复

    你好,Elvis Lee,这俩是有效方法~很不错~

    2022-11-24 13:39:56

  • 移横为固

    2022-11-23 16:58:22

    有简单使用clickhouse,考虑到clickhouse的特性,对需要修改的数据是不放入clickhouse存储。在历史数据清理上,使用过两个方法:
    1.clickhouse支持过期删除策略,可以根据表中的时间字段设置过期时间,让clickhouse帮忙自动删除过期数据。
    2.clickhouse存储数据会对数据进行分区存储,建表时就可以设置好分区字段,类似平常所说的水平分表。在删除数据时可以查找到表的分区信息,按分区删除数据。
    作者回复

    你好,移横为固,这个方式很不错~

    2022-11-23 20:59:49