clickhouse学习

一、参考资料

1、官方文档

2、大数据技术与数仓-clickhouse专栏

二、特点

  1. 数据压缩

  2. 列式存储

  3. 分布式查询

    数据可以在不同的分片上保存,查询可以在所有分片上并行处理

  4. 支持索引

  5. 列向量引擎,高效利用cpu资源

  6. 支持近似计算加速查询

三、引擎

MergeTree

  • 简介

    1. 执行高负载任务的最通用和最强大的表引擎
    2. 数据总会以数据片段的形式写入磁盘,且数据片段不可修改
    3. 后台线程定时将数据片段合并
  • 特点

    1. 存储的数据按照主键排序:允许创建稀疏索引,从而加快数据查询速度
    2. 支持分区,可以通过PARTITION BY语句指定分区字段
    3. 支持数据副本
    4. 支持数据采样
  • MergeTree表引擎

    建表语法:

    CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
    (
        name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1],
        name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2],
        ...
        INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,
        INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2
    ) ENGINE = MergeTree()
    ORDER BY expr
    [PARTITION BY expr]
    [PRIMARY KEY expr]
    [SAMPLE BY expr]
    [TTL expr [DELETE|TO DISK 'xxx'|TO VOLUME 'xxx'], ...]
    [SETTINGS name=value, ...]
    

    ENGINE:ENGINE = MergeTree(),MergeTree引擎没有参数

    ORDER BY:排序字段。比如ORDER BY (Col1, Col2),值得注意的是,如果没有指定主键,默认情况下 sorting key(排序字段)即为主键。如果不需要排序,则可以使用ORDER BY tuple()语法,这样的话,创建的表也就不包含主键。这种情况下,ClickHouse会按照插入的顺序存储数据。必选。

    PARTITION BY:分区字段,可选。

    PRIMARY KEY:指定主键,如果排序字段与主键不一致,可以单独指定主键字段。否则默认主键是排序字段。可选。

    SAMPLE BY:采样字段,如果指定了该字段,那么主键中也必须包含该字段。比如SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))。可选。

    TTL:数据的存活时间。在MergeTree中,可以为某个列字段或整张表设置TTL。当时间到达时,如果是列字段级别的TTL,则会删除这一列的数据;如果是表级别的TTL,则会删除整张表的数据。可选。

    SETTINGS:额外的参数配置。可选。

  • ReplacingMergeTree表引擎

    1. 建表语法:

      CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
      (
          name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
          name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
          ...
      ) ENGINE = ReplacingMergeTree([ver])
      [PARTITION BY expr]
      [ORDER BY expr]
      [PRIMARY KEY expr]
      [SAMPLE BY expr]
      [SETTINGS name=value, ...]
      
    2. 去重

      • 判断去重:

        ReplacingMergeTree在去除重复数据时,是以ORDERBY排序键为基准的,而不是PRIMARY KEY

      • 何时删除重复数据

        执行分区合并时,会触发删除重复数据,有台线程自动删除,也可以手动合并,手动合并代码

        optimize table_name final
        
      • 不同分区的重复数据不会被去重

      • 去重策略

        如果没有设置[ver]版本号,则保留同一组重复数据中的最新插入的数据;如果设置了[ver]版本号,则保留同一组重复数据中ver字段取值最大的那一行

      • optimize命令使用

        数据量大的情况下尽量不要使用,因为要消耗大量时间

  • SummingMergeTree表引擎

    1. 建表语法

      CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
      (
          name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
          name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
          ...
      ) ENGINE = SummingMergeTree([columns]) -- 指定合并汇总字段
      [PARTITION BY expr]
      [ORDER BY expr]
      [SAMPLE BY expr]
      [SETTINGS name=value, ...]
      
    2. 把具有相同主键的行合并成一行,该行包含了被合并的行中具有数值数据类型的列的汇总值

    3. 如果未指定聚合字段,会按照非主键的数值类型字段进行聚合

    4. 未指定的聚合字段,则会保留最早的那一条

  • Aggregatingmergetree表引擎

    通过预先定义的聚合函数计算数据,可以指定各种的聚合函数

  • CollapsingMergeTree表引擎

    1. 建表语法

      CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
      (
          name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
          name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
          ...
      ) ENGINE = CollapsingMergeTree(sign)
      [PARTITION BY expr]
      [ORDER BY expr]
      [SAMPLE BY expr]
      [SETTINGS name=value, ...]
      
    2. 以增代删,支持行级数据修改和删除的表引擎

    3. 通过定义一个sign标记位字段,记录数据行的状态。如果sign标记为1,则表示这是一行有效的数据;如果sign标记为-1,则表示这行数据需要被删除。当CollapsingMergeTree分区合并时,同一数据分区内,sign标记为1和-1的一组数据会被抵消删除

    4. 限制

      • 数据写入有严格的顺序,否则可能导致无法正常折叠
      • 单线程执行可以较好控制数据写入顺序,多线程不能保证
  • VersionedCollapsingMergeTree表引擎

    1. 建表语法

      CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
      (
          name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
          name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
          ...
      ) ENGINE = VersionedCollapsingMergeTree(sign, version)
      [PARTITION BY expr]
      [ORDER BY expr]
      [SAMPLE BY expr]
      [SETTINGS name=value, ...]
      
    2. 解决CollapsingMergeTree表引擎数据乱序不能折叠的问题

    3. 建表除了需要指定一个sign标识之外,还需要指定一个UInt8类型的version版本号

Log引擎

  • 场景

    主要用于快速写入小表(1百万行左右的表),然后全部读出的场景。即一次写入多次查询

  • 特点

    1. 数据存储在磁盘上,写入数据时直接追加
    2. 不支持并发读写,当表写入时,会阻塞表的读取查询
    3. 不支持原子写,当写入中断时,可能会获得带有损坏数据的表
    4. 不支持索引
    5. 不支持alter操作,例如update、delete
  • TinyLog表引擎

    1. 建表语法

      CREATE TABLE testlog (
        column_name Uint16 comment '列'
        ...
        )ENGINE=TinyLog();
      
    2. 由每一列的数据文件和一个元数据文件组成

    3. 不支持并发读数据

  • StripLog表引擎

    1. 支持并行查询
    2. 所有列数据存储在同一个文件中,减少了文件的使用数量
    3. 由3个文件组成
      • data.bin数据文件,保存所有列的数据
      • .mrk标记文件,保存了数据在data.bin文件中的位置信息,便于多线程查找数据,提高查询效率
      • size.json元数据文件,记录其余两个文件的大小
  • Log引擎表

    适用于临时数据,一次性写入,结合以上两个表引擎的优点,是Log系列引擎中性能最高的表引擎

集成引擎

  • 与其它数据存储以及处理系统集成的引擎,如 Kafka,MySQL 以及 HDFS

  • kafka引擎

    1. 建表语法

        CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
        (
          name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
          name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
          ...
        ) ENGINE = Kafka()
        SETTINGS
          kafka_broker_list = 'host:port',
          kafka_topic_list = 'topic1,topic2,...',
          kafka_group_name = 'group_name',
          kafka_format = 'data_format'[,]
          [kafka_row_delimiter = 'delimiter_symbol',]
          [kafka_schema = '',]
          [kafka_num_consumers = N,]
          [kafka_max_block_size = 0,]
          [kafka_skip_broken_messages = N,]
          [kafka_commit_every_batch = 0,]
          [kafka_thread_per_consumer = 0]
      
    2. 注意

      一旦查询完毕之后,ClickHouse会删除表内的数据,其实Kafka表引擎只是一个数据管道,可以通过物化视图的方式访问Kafka中的数据

    3. 开发流程

      一般需要三张表:

      1. kafka表,负责描述topic,消费数据和解析数据

      2. MergeTree表,存kafka数据

      3. 物化视图,用来把kafka表和MergeTree表关联起来

        create materialized view test_view to merge_tree_table as select * from kafka_table

  • 特殊引擎

    用于一些特定的功能,如 Distributed 用于分布式查询,MaterializedView 用来聚合数据,以及 Dictionary 用来查询字典数据等

    例如Distributed表引擎是分布式表的代名词,它自身不存储任何数据,数据都分散存储在某一个分片上,能够自动路由数据至集群中的各个节点,所以Distributed表引擎需要和其他数据表引擎一起协同工作

    创建分布式表:

    CREATE TABLE IF NOT EXISTS table_dist ON CLUSTER cluster_name
    (
        column1 Int32,
        column2 String
    )ENGINE = Distributed(cluster_name, db_name, local_table_name [,sharding_key]);
    /*
    cluster_name:集群名称,与集群配置中的自定义名称相对应。
    db_name:数据库名称
    local_table_name:表名称
    sharding_key:可选的,用于分片的key值,在数据写入的过程中,分布式表会依据分片key的规则,将数据分布到各个节点的本地表。
    */
    

    创建分布式表是读时检查的机制,也就是说对创建分布式表和本地表的顺序并没有强制要求

    接着就可以在每台机器上看到刚刚创建的分布式表了,然后可以在每台机器上创建一张本地表该分布式表映射的本地表了

数据副本

数据副本可以查看这里

四、开发

  • 常见问题

    1. 数据插入报错 too many parts exception

      原因:数据写入过于频繁,导致后台merge分片速度缓慢,ch拒绝数据写入

      解决:可以增加每次数据写入的batch_size(例如10万),或者增大写入数据的间隔时间

    2. 复制表变为只读

      原因:ClickHouse 无法连接 ZooKeeper 集群或 ZooKeeper 上该复制表的元数据丢失导致的,此时新数据无法插入该表

    3. 执行 JOIN 操作时内存超限

      原因:没有进行数据过滤,或者join本身的数据量很大

      解决:修改配置文件中的内存限制

    4. 直接写入方式

      1. 写入分布式表
        • 先放入本次磁盘的缓冲区,然后再分发给所有节点的MergeTree表
        • 风险
          1. 在分发给MergeTree表时节点宕机,会造成数据丢失
          2. 在节点宕机恢复后重新分发数据,可能会造成数据重复写入
          3. 分发生成更多的小文件,拖垮系统
      2. 写入MergeTree表
        • 解决数据分发问题,但依然扛不住高频的数据写入
        • 需要控制好写入数量和写入时间间隔,不然可能会造成后台合并数据分片的速度会慢于数据写入数据,造成数据写入拒绝
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容