问题描述

​ 由于业务限制,数据库中存在大量重复数据,故采用了ReplacingMergeTree表引擎,但后台始终没有进行数据合并。

  • 建表语句

    1CREATE TABLE xxxx.xxxx ON CLUSTER xxx
    2(
    3    user_id String,
    4    name String,
    5 )
    6ENGINE = ReplacingMergeTree()
    7ORDER BY (user_id);
    8
    9CREATE TABLE xxxx.xxxx ON CLUSTER xxx as xxxx.xxxx ENGINE = Distributed('xxxx', 'xxxx', xxxx, rand());
    
  • 查询数据是否有重复

    1SELECT COUNT() FROM xxxx.xxxx
    241905623
    3
    4SELECT COUNT(x) FROM (SELECT x FROM xxxx.xxxx GROUP BY [oder_key]) 
    541705616
    
  • 手动执行数据合并,也没有去除重复数据

    1OPTIMIZE TABLE ~ ON CLUSTER ~ FINAL
    2
    3SELECT COUNT() FROM xxxx.xxxx
    441905623
    

思考

​ 分布式表存储数据采用分片存储,如6条数据存3个节点,则每个节点存储2条数据。当发生数据合并时,可能只合并当前节点的数据。最终也在这https://stackoverflow.com/questions/62616949/deduplication-in-distributed-clickhouse-table,验证了这一猜想。

解决

​ 创建分布式表时,不使用rand()进行随机分布,使用user_id进行分片,使相同user_id的数据在写入时落在相同的节点。

1CREATE TABLE xxxx.xxxx ON CLUSTER xxx as xxxx.xxxx ENGINE = Distributed('xxxx', 'xxxx', xxxx, user_id);