• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

ClickHouse 复制表引擎重复数据没办法写入

武飞扬头像
oldba.cn
帮助1

关于复制表重复数据无法写入,这里进行一下演示和剖析。有时候,我们明明已经插入了数据,可是查询到的数据行数并没有新增,现对该情况进行分析。

--演示说明

CREATE TABLE try
(
    `username` String, 
    `lables.name` Array(String), 
    `lables.value` Array(String), 
    `day` Date
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/try', '{replica}')
PARTITION BY toYYYYMMDD(day)
ORDER BY username;

insert into try values ('张三',['os_type','version','database_name','owner'],['linux','redhat_7.6','postgres','postgres'],toDate(now()));
insert into try values ('李四',['os_type','version','database_name','owner'],['linux','redhat_7.7','flyingdb','flyingdb'],toDate(now()));
insert into try values ('王五',['os_type','version','database_name','owner'],['linux','Mint_17.3','test','test'],today());
insert into try values ('赵六',['os_type','version','database_name','owner'],['linux','Mint_17.4','data','data'],today());

select * from try;
┌─username─┬─lables.name───────────────────────────────────┬─lables.value────────────────────────┬────────day─┐
│ 赵六     │ ['os_type','version','database_name','owner'] │ ['linux','Mint_17.4','data','data'] │ 2022-09-14 │
└──────────┴───────────────────────────────────────────────┴─────────────────────────────────────┴────────────┘
┌─username─┬─lables.name───────────────────────────────────┬─lables.value─────────────────────────────────┬────────day─┐
│ 李四     │ ['os_type','version','database_name','owner'] │ ['linux','redhat_7.7','flyingdb','flyingdb'] │ 2022-09-14 │
└──────────┴───────────────────────────────────────────────┴──────────────────────────────────────────────┴────────────┘
┌─username─┬─lables.name───────────────────────────────────┬─lables.value────────────────────────┬────────day─┐
│ 王五     │ ['os_type','version','database_name','owner'] │ ['linux','Mint_17.3','test','test'] │ 2022-09-14 │
└──────────┴───────────────────────────────────────────────┴─────────────────────────────────────┴────────────┘
┌─username─┬─lables.name───────────────────────────────────┬─lables.value─────────────────────────────────┬────────day─┐
│ 张三     │ ['os_type','version','database_name','owner'] │ ['linux','redhat_7.6','postgres','postgres'] │ 2022-09-14 │
└──────────┴───────────────────────────────────────────────┴──────────────────────────────────────────────┴────────────┘
学新通

重复执行上面insert数据,然后select数据,发现数据还是只有4行。

分析日志,有如下日志记录:

2022.09.14 17:01:20.725741  [ 163 ] {67719eb7-2f61-41b7-8abb-bcf2e67d6ae8} <Error> executeQuery: Code: 57, e.displayText() = DB::Exception: Table icat.try already exists. (version 20.2.1.2120 (official build)) (from 127.0.0.1:36636) (in query: CREATE TABLE icat.try (`username` String, `lables.name` Array(String), `lables.value` Array(String), `day` Date) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/try', '{replica}') PARTITION BY toYYYYMMDD(day) ORDER BY username), Stack trace (when copying this message, always include the lines below):

可以发现,新插入的数据被clickhouse过滤掉了。那么,来看下ClickHouse的处理逻辑。

# 数据插入入口
InterpreterInsertQuery::execute
    StorageReplicatedMergeTree::write // 构造数据流 ReplicatedMergeTreeBlockOutputStream
        deduplicate = replicated_deduplication_window != 0 && insert_deduplicate // 是否去重,跟去重窗口和去重标志有关,默认窗口为100,标志为true
        
    ReplicatedMergeTreeBlockOutputStream::write // 数据写入
        block转为part
        if deduplicate == true
            hash // part的哈希值
            block_id = partition_id   "_"   hash.words[0]   "_"   hash.words[1] // 构造block_id的字符串名称
        end
        
        commitPart // 向zk提交part
            if block_id not empty
                zkutil::makeCreateRequest // 如果zk上有相同的节点,则返回空block_number,否则创建该节点
            end
            
            if getActiveContainingPart
                return // 该part已经被包含,则忽略它
# 复制表清理线程
ReplicatedMergeTreeCleanupThread::run
    sleep_ms // 周期间隔时间,默认30s~40s随机
    ReplicatedMergeTreeCleanupThread::iterate
        clearOldBlocks // 清理过期block
            replicated_deduplication_window_seconds
            replicated_deduplication_window // 两者综合考虑,超过replicated_deduplication_window或者之间间隔超过replicated_deduplication_window_seconds
学新通

在默认情况下,如果一次插入的数据与一周内最近的100次左右(如果一次性插入的block可以分为多个part,则不到100次)成功插入的数据具有相同的block_id,则会被过滤掉。

针对这个问题官方有个参数:insert_deduplicate

对于 Replicated* 表,启用或禁用INSERT删除重复数据。

可能的值:

        0 -禁用。

        1 -启用(默认值)。

默认情况下,通过INSERT语句插入到复制表中的块会被重复数据删除(请参阅数据复制)

https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/replication

insert_deduplicate参数配置三种方式:

1.在 users.xml 中的用户配置文件中

2.SET 命令的会话

3.在SELECT语句的 SETTINGS 子句中。

通过设置可以让clickhouse不做此项检查,保证数据每次都能插入成功。有点需要注意的是,真正生效的窗口大小可能不止100,可能更多。因为清理线程的周期是30-40s,如果老的block_id没有及时清理掉,会导致实际的去重窗口值大于replicated_deduplication_window。

声明

因小编个人水平有限,专栏中难免存在错漏之处,请勿直接复制文档中的参数、命令或方法应用于线上环境中操作。

近期文章推荐

ClickHouse 版本升级
PostgreSQL 逻辑复制模块(一)
PostgreSQL 逻辑复制模块(二)

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgcakjb
系列文章
更多 icon
同类精品
更多 icon
继续加载