我不清楚这两个词。一个块是否具有固定的行数?从磁盘读取的最小单位是否为一个块?是否将不同的块存储在不同的文件中?一格的范围是否比颗粒大?这就是说,一个块可以具有多个颗粒跳过索引。
https://clickhouse.tech/docs/en/development/architecture/#block
块可以包含任意数量的行。例如1个行块:
set max_block_size=1;
SELECT * FROM numbers_mt(1000000000) LIMIT 3;
┌─number─┐
│ 0 │
└────────┘
┌─number─┐
│ 2 │
└────────┘
┌─number─┐
│ 3 │
└────────┘
set max_block_size=100000000000;
create table X (A Int64) Engine=Memory;
insert into X values(1);
insert into X values(2);
insert into X values(3);
SELECT * FROM X;
┌─A─┐
│ 1 │
└───┘
┌─A─┐
│ 3 │
└───┘
┌─A─┐
│ 2 │
└───┘
块中3行
drop table X;
create table X (A Int64) Engine=Memory;
insert into X values(1)(2)(3);
select * from X
┌─A─┐
│ 1 │
│ 2 │
│ 3 │
└───┘
主键稀疏。默认情况下,每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字节=== 2个INT64的值。
自适应索引粒度意味着颗粒大小各不相同。因为(为了提高性能)宽行(许多字节)需要较少的颗粒(<8192)行。
index_granularity_bytes = 10MB〜1k行*8129。因此每个颗粒都有10MB。如果行大小为100k(长字符串),则颗粒将有100行(不是8192)。
跳过索引粒度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个表的颗粒。
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检查的跳过索引-由于77不在0..63中,因此可以跳过4个表粒度。并且必须读取另外4个颗粒(4标记),因为(64..128)中的77-这4个颗粒中的一些具有B = 77。