问题描述
由于业务限制,数据库中存在大量重复数据,故采用了ReplacingMergeTree表引擎,但后台始终没有进行数据合并。
建表语句
CREATE TABLE xxxx.xxxx ON CLUSTER xxx ( user_id String, name String, ) ENGINE = ReplacingMergeTree() ORDER BY (user_id); CREATE TABLE xxxx.xxxx ON CLUSTER xxx as xxxx.xxxx ENGINE = Distributed('xxxx', 'xxxx', xxxx, rand());
查询数据是否有重复
SELECT COUNT() FROM xxxx.xxxx 41905623 SELECT COUNT(x) FROM (SELECT x FROM xxxx.xxxx GROUP BY [oder_key]) 41705616
手动执行数据合并,也没有去除重复数据
OPTIMIZE TABLE ~ ON CLUSTER ~ FINAL SELECT COUNT() FROM xxxx.xxxx 41905623
思考
分布式表存储数据采用分片存储,如6条数据存3个节点,则每个节点存储2条数据。当发生数据合并时,可能只合并当前节点的数据。最终也在这https://stackoverflow.com/questions/62616949/deduplication-in-distributed-clickhouse-table,验证了这一猜想。
解决
创建分布式表时,不使用rand()进行随机分布,使用user_id进行分片,使相同user_id的数据在写入时落在相同的节点。
CREATE TABLE xxxx.xxxx ON CLUSTER xxx as xxxx.xxxx ENGINE = Distributed('xxxx', 'xxxx', xxxx, user_id);