首页 > 解决方案 > 如何理解 ClickHouse 中的粒度和块?

问题描述

这两个词我不是很清楚。一个块是否有固定的行数?一个块是否是从磁盘读取的最小单位?不同的块是否存储在不同的文件中?一个块的范围是否大于颗粒?这意味着,一个块可以有多个颗粒跳过索引。

标签: clickhouse

解决方案


https://clickhouse.tech/docs/en/operations/table_engines/mergetree/#primary-keys-and-indexes-in-queries

主键是稀疏的。默认情况下,它包含每 8192 行中的 1 个值(= 1 个颗粒)。

让我们禁用自适应粒度(用于测试)-- index_granularity_bytes=0

create table X (A Int64) 
Engine=MergeTree order by A 
settings index_granularity=16,index_granularity_bytes=0;

insert into X select * from numbers(32);

index_granularity=16 -- 32 行 = 2 个粒度,主索引有 2 个值 0 和 16

select marks, primary_key_bytes_in_memory from system.parts where table = 'X';
┌─marks─┬─primary_key_bytes_in_memory─┐
│     2 │                          16 │
└───────┴─────────────────────────────┘

16 个字节 === INT64 的 2 个值。

自适应索引粒度意味着粒度大小不同。因为宽行(很多字节)需要(为了性能)更少的(<8192)行。

index_granularity_bytes = 10MB ~ 1k row * 8129. 所以每个颗粒有 10MB。如果行大小为 100k(长字符串),则颗粒将有 100 行(不是 8192)。


Skip index granules GRANULARITY 3 - 表示索引将为每 3 个表颗粒存储一个值。

create table X (A Int64, B Int64, INDEX IX1 (B) TYPE minmax GRANULARITY 4) 
Engine=MergeTree order by A 
settings index_granularity=16,index_granularity_bytes=0;

insert into X select number, number from numbers(128);

128/16 = 8,表有 8 个颗粒,INDEX IX1 存储 2 个 minmax (8/4) 值

所以 minmax 索引存储 2 个值 - (0..63) 和 (64..128)

0..63 -- 指向前 4 个表的颗粒。

64..128 -- 指向第二个 4 table' 颗粒。

set send_logs_level='debug'
select * from X where B=77
[ 84 ] <Debug> dw.X (SelectExecutor): **Index `IX1` has dropped 1 granules**
[ 84 ] <Debug> dw.X (SelectExecutor): Selected 1 parts by date, 1 parts by key, **4 marks** to read from 1 ranges

SelectExecutor 检查跳过索引 - 可以跳过 4 个表颗粒,因为 77 不在 0..63 中。并且必须读取另外 4 个颗粒(4 个标记),因为 77 in (64..128) - 其中一些 4 个颗粒的 B=77。


推荐阅读