美文网首页
clickhouse学习

clickhouse学习

作者: 无暇的风笛 | 来源:发表于2021-12-15 09:54 被阅读0次

    一、参考资料

    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表
          • 解决数据分发问题,但依然扛不住高频的数据写入
          • 需要控制好写入数量和写入时间间隔,不然可能会造成后台合并数据分片的速度会慢于数据写入数据,造成数据写入拒绝

    相关文章

      网友评论

          本文标题:clickhouse学习

          本文链接:https://www.haomeiwen.com/subject/yyqyfrtx.html