当前位置: 首页>后端>正文

数据存储-clickhouse

clickhouse 数据存储 相关概念

  • granule

granule

granule:颗粒的意思。
颗粒由很多行组成。一个颗粒对应一个索引项。clickhouse为每个颗粒
建立一个索引,这也就是稀疏索引的名称的来源。

与 granule 大小相关的配置参数

index_granularity_bytes:满足多少字节大小 划分为一个颗粒
index_granularity:多少行数划分为一个颗粒

clickhouse 在磁盘上的数据存储位置

默认的存储路径是 /var/lib/clickhouse 目录

clickhouse 某个数据库下的某个表的数据 在磁盘上的存储路径。

假设默认的存储路径为 /var/lib/clickhouse

/var/lib/clickhouse/data/数据库名/表名
这个目录对应着一个表在磁盘上的数据存储。当然这个目录是一个软链接

clickhouse 表的元数据 在磁盘上的存储路径。

/var/lib/clickhouse/metadata/数据库名/表名
注意:可复制表的元数据 还会在 zookeeper 之中存储一份。

clickhouse 数据存储 是列式存储 还是行式存储

列式存储。
在数据量比较小的情况下,一行的所有列都存储在磁盘上的一个文件之中。
数据量大的情况下,不同的列各自对应着磁盘上的一个文件。
具体的划分标准由具体的参数来控制。

clickhouse 数据存储路径 相关的配置参数

config.xml 配置文件之中的 path 参数,参数含义为 指定数据在磁盘上的存储位置。

clickhouse part 在磁盘上的表现形式

part 是磁盘上的一个目录,目录下的文件可能有以下这些

  • checksums.txt:存储校验和,用来判断data_part 是否损坏
  • columns.txt:存储字段的信息
  • count.txt:存储这个data_part之中的数据行数
  • default_compression_codec.txt:存储默认的压缩算法类型
  • partition.dat :设置了分区键之后才会生成的文件,存储当前分区表达式生成的值
  • minmax_[column].idx:设置了分区键之后才会生成的文件, 存储当前分区的分区键的原始列的最大值和最小值
    *xxx.bin:存储数据的文件。前缀是字段名。数据的压缩文件
  • xxx.mrk2/3:存储block 以及 granule 在文件之中的偏移量。数据的标记文件
  • primary.idx: 索引文件

primary.idx

存储每一个granule之中,索引列的最小值的相关信息。

xxx.[mrk2]/[mrk3] 标记文件

存储每一个索引对应的数据在物理文件上的对应位置

clickhouse 表数据在磁盘上的组织关系

由表的元数据信息 primary key 字段 , 以及 order by 的字段来决定表之中的数据在磁盘上的存储方式。
clickhouse表数据是排序过后在磁盘上进行存储的,所依据的排序规则为 表的 primary key 字段 和 order by 字段, 并以正向排序。clickhouse 会根据表的index_granularity设置值,例如index_granularity 默认值为 8192,那么为排序后的数据,按照8192行,生成一个索引记录,索引记录之中存储的是 每一个颗粒之中的第一行所包含的主键字段的值。clickhouse 还会对每个列生成一个mrk[2]/[3] 类型的文件,文件之中的每一行记录表示存储的是 此字段在某个granule之中第一行在物理文件之中的具体位置,用以读取数据时定位。

注意:
1: primary key 之中的字段 一定是 order by 字段的前缀。
2:mrk[2]/[3] 文件之中存储的数据是一个数组,数组的每个元素是 [block_offset, granule_offset]
block_offset 则是列式存储 而产生的block概念,用以表示block的具体位置。
granule_offset 是指 某个granule之中第一行在xxx.bin文件之中的具体位置。

压缩算法

注意:压缩算法所针对的对象是表之中的列,所以可以对一个表的不同的字段设置压缩算法。

查看表的某个字段所使用的压缩算法

select compression_codec from system.columns where table = '表名'

注意:如果输出的值为空,那么应用的是默认的压缩算法,默认的压缩算法是lz4。

如何修改表字段所使用的压缩算法

使用 alter table 语句修改表的字段结构,来修改表字段所使用的压缩算法。

监控

磁盘使用量监控

建议使用 node-exporter + prometheus 进行监控。

查看各个表的 分区数 主键索引的大小 未压缩后的数据大小 压缩后的数据大小 在磁盘上占据的总大小

注:在磁盘上占据的总大小 约等于 压缩后的数据大小 + 主键索引的大小

     select
         database,
         table,
        count(*) as partition_num, // 分区数 
        sum(primary_key_bytes_in_memory) as primary_key_bytes_in_memory, // 主键索引的大小
        sum(data_uncompressed_bytes) as data_uncompressed_bytes, // 未压缩的数据量大小
        sum(data_compressed_bytes) as data_compressed_bytes, // 压缩后的数据量大小
        sum(bytes_on_disk) as bytes_on_disk // 在磁盘上占据的总大小
     from (
     select
        database,
        table,
        partition,
        sum(primary_key_bytes_in_memory) as primary_key_bytes_in_memory, 
        sum(data_uncompressed_bytes) as data_uncompressed_bytes,
        sum(data_compressed_bytes) as data_compressed_bytes,
        sum(bytes_on_disk) as bytes_on_disk
     from
          clusterAllReplicas('default', 'system.parts')
     where active = 1
     group by
     database,
     table,
     partition
     ) a
     group by database, table
     order by bytes_on_disk  desc

各节点不活跃的part 数目 以及数据量

select
  hostName,
  count(*) as num,
  sum(bytes_on_disk) as bytes_on_disk
from (
   select 
      hostName() as hostName,
      bytes_on_disk
   from
     clusterAllReplicas('default', 'system.parts')
   where active = 0
) 
group by
hostName

小技巧

查看某个压缩数据文件的信息

clickhouse-compressor --stat xxx.bin
这样会显示每一个块的未压缩前的数据量大小,以及压缩后的数据量大小。

问题

2:为什么索引文件之中不直接存储对应字段的物理位置,而是拆分出一个个mrk类型的文件进行存储呢?
一个原因是因为索引文件会被加载到内存之中,索引文件越小,则占据的内存越小。毕竟是针对大数据量的场景。另一个方面,针对列裁剪输出,如果只需输出两列,那么可能只需要加载此两列所对应的mrk文件,也是减小了内存的消耗。


https://www.xamrdz.com/backend/3ad1938410.html

相关文章: