clickhouse的多路径存储策略
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
clickhouse的多路径存储策略
个⼈学习笔记,谢绝转载
clickhouse从19.15开始,MergeTree实现了⾃定义存储策略的功能:
JBOD策略:这种策略适合服务器挂多磁盘但没做raid的场景。
JBOD是⼀种轮询策略,每次执⾏INSERT或者MERGE,所以产⽣的新分区会轮询写⼊各个磁盘。
这种策略可以减低单盘负载,在⼀定条件下提升数据并⾏读写的性能。
HOT/COLD策略:这种策略适合服务挂不通类型磁盘的场景。
将磁盘分为HOT与COLD两类区域,HOT区使⽤⼩容量⾼速存储,注重存取性能;COLD区使⽤⼤容量低速存储,注重容量。
MergeTree写⼊时,会在HOT区创建分区⽬录保存数据,当分区数据达到阈值,数据⾃动移动到COLD区。
每个区内部也⽀持定义多个磁盘,⽀持JBOD策略。
配置语法
storage_configuration 标签定义多路径存储策略
disks 标签定义磁盘
policies 标签定义策略
<storage_configuration>
<!-- 定义磁盘 -->
<disks>
<disk_name_01> <!-- ⾃定义磁盘名称,全局唯⼀ -->
<path>/path/to/disk_name_01/</path> <!-- 磁盘路径 -->
<keep_free_space_bytes>21474836480</keep_free_space_bytes>
</disk_name_01>
<disk_name_02>
<path>/path/to/disk_name_02/</path>
<keep_free_space_bytes>21474836480</keep_free_space_bytes>
</disk_name_02>
</disks>
<!-- 定义策略>
<policies>
<policy_name> <!-- ⾃定义策略名称,全局唯⼀ -->
<!-- 定义volume -->
<volumes>
<volume_name_01> <!-- ⾃定义volum名称,全局唯⼀ -->
<disk>disk_name_01</disk> <!-- 指定该volume下使⽤的磁盘,磁盘名称要和上⾯定义的对应 -->
<disk>disk_name_02</disk>
<max_data_part_size_bytes>1073741824</max_data_part_size_bytes>
</volume_name_01>
</volumes>
<move_factor>0.2</move_factor>
</policy_name>
</policies>
</storage_configuration>
keep_free_space_bytes: 选填项,⽤于指定指定磁盘的预留空间,单位字节bit。
max_data_part_size_bytes:选填,字节为单位默认1G,表⽰在这个卷的单个disk磁盘中,⼀个数据分区的最⼤磁盘存储阈值,若当前分区的数据⼤⼩超过阈值,则之后的分区会写⼊下⼀个disk磁盘。
move_factor:选填项,默认值为0.1,;若当前卷的可⽤空间⼤⼩⼩于factor因⼦,并且定义多个卷,则数据会⾃动移动到下⼀个卷。
JBOD
配置:
<storage_configuration>
<disks>
<disk_01>
<path>/data/chbase/data_01/</path>
</disk_01>
<disk_02>
<path>/data/chbase/data_02/</path>
</disk_02>
<disk_03>
<path>/data/chbase/data_03/</path>
</disk_03>
</disks>
<policies>
<jbod_policies>
<volumes>
<jbod_volume>
<disk>disk_01</disk>
<disk>disk_02</disk>
</jbod_volume>
</volumes>
</jbod_policies>
</policies>
</storage_configuration>
查看disk配置:
localhost :) SELECT name, path, formatReadableSize(free_space) AS free, formatReadableSize(total_space) AS total, formatReadableSize(keep_free_space) AS reserved FROM system.disks;┌─name────┬─path────────────────────────────┬─free──────┬─total─────┬─reserved─┐
│ default │ /data/database/clickhouse/data/ │ 13.19 GiB │ 29.98 GiB │ 0.00 B │
└─────────┴─────────────────────────────────┴───────────┴───────────┴──────────┘
查看policies策略:
localhost :) SELECT policy_name, volume_name, volume_priority, disks, formatReadableSize(max_data_part_size) AS max_data_part_size, move_factor FROM system.storage_policies;
┌─policy_name───┬─volume_name─┬─volume_priority─┬─disks─────────────────┬─max_data_part_size─┬─move_factor─┐
│ default │ default │ 1 │ ['default'] │ 0.00 B │ 0 │
│ jbod_policies │ jbod_volume │ 1 │ ['disk_01','disk_02'] │ 0.00 B │ 0.1 │
└───────────────┴─────────────┴─────────────────┴───────────────────────┴────────────────────┴─────────────┘
建表测试:
##使⽤settings storage_policy='jbod_policies'指定策略
localhost :) CREATE TABLE jbod_table_v1
(
`id` UInt64
)
ENGINE = MergeTree()
ORDER BY id
SETTINGS storage_policy = 'jbod_policies'
##写⼊第⼀批数据,创建第⼀个分区⽬录
localhost :) INSERT INTO jbod_table_v1 SELECT rand() FROM numbers(10);
##查看系统分区表,可以看到第⼀个分区all_1_1_0被写⼊到disk_01
localhost :) SELECT name, disk_name FROM system.parts WHERE table='jbod_table_v1';
┌─name──────┬─disk_name─┐
│ all_1_1_0 │ disk_01 │
└───────────┴───────────┘
##写⼊第⼆批数据,创建第⼆个分区⽬录
localhost :) INSERT INTO jbod_table_v1 SELECT rand() FROM numbers(10);
##可以看到第⼆个分区all_2_2_0被写⼊到disk_02
localhost :) SELECT name, disk_name FROM system.parts WHERE table='jbod_table_v1';
┌─name──────┬─disk_name─┐
│ all_1_1_0 │ disk_01 │
│ all_2_2_0 │ disk_02 │
└───────────┴───────────┘
##反复⼏次
localhost :) SELECT name, disk_name FROM system.parts WHERE table='jbod_table_v1';
┌─name──────┬─disk_name─┐
│ all_1_1_0 │ disk_01 │
│ all_2_2_0 │ disk_02 │
│ all_3_3_0 │ disk_01 │
│ all_4_4_0 │ disk_02 │
└───────────┴───────────┘
JBOD策略,每当⽣成⼀个新数据分区的时候,分区⽬录会根据volume中定义的disk顺序依次轮询并写⼊各个disk。
HOT/COLD
配置:
<storage_configuration>
<disks>
<disk_01>
<path>/data/chbase/data_01/</path>
</disk_01>
<disk_02>
<path>/data/chbase/data_02/</path>
</disk_02>
<clod_disk>
<path>/data/chbase/cold_data/</path>
<keep_free_space_bytes>21474836480</keep_free_space_bytes>
</clod_disk>
</disks>
<policies>
<hot_to_cold>
<volumes>
<hot_volume>
<disk>disk_01</disk>
<disk>disk_02</disk>
<max_data_part_size_bytes>1048576</max_data_part_size_bytes>
</hot_volume>
<cold_volume>
<disk>clod_disk</disk>
</cold_volume>
</volumes>
<move_factor>0.2</move_factor>
</hot_to_cold>
</policies>
</storage_configuration>
查看disk配置:
localhost :) SELECT name, path, formatReadableSize(free_space) AS free, formatReadableSize(total_space) AS total, formatReadableSize(keep_free_space) AS reserved FROM system.disks;┌─name──────┬─path────────────────────────────┬─free──────┬─total─────┬─reserved──┐
│ disk_02 │ /data/chbase/data_02/ │ 9.96 GiB │ 9.99 GiB │ 0.00 B │
└───────────┴─────────────────────────────────┴───────────┴───────────┴───────────┘
查看policies策略:
localhost :) SELECT policy_name, volume_name, volume_priority, disks, formatReadableSize(max_data_part_size) AS max_data_part_size, move_factor FROM system.storage_policies;
┌─policy_name─┬─volume_name──┬─volume_priority─┬─disks─────────────────┬─max_data_part_size─┬─move_factor─┐
│ default │ default │ 1 │ ['default'] │ 0.00 B │ 0 │
│ hot_to_cold │ hot_volume │ 1 │ ['disk_01','disk_02'] │ 1.00 GiB │ 0.2 │
│ hot_to_cold │ cold_volume │ 2 │ ['clod_disk'] │ 0.00 B │ 0.2 │
└─────────────┴──────────────┴─────────────────┴───────────────────────┴────────────────────┴─────────────┘
可以看出,hot_to_cold策略有两个volume: hot_volume、cold_volume。
其中hot_volume有两块磁盘:disk_01、disk_02。
建表测试:
localhost : CREATE TABLE htc_table_1
(
`id` UInt64
)
ENGINE = MergeTree()
ORDER BY id
SETTINGS storage_policy = 'hot_to_cold';
##写⼊两个分区
localhost :) INSERT INTO htc_table_1 SELECT rand() FROM numbers(100000);
##查看两次⽣成的分区采⽤JBOD策略均衡在disk_01、disk_02
localhost :) SELECT name, disk_name FROM system.parts WHERE table='htc_table_1';
┌─name──────┬─disk_name─┐
│ all_1_1_0 │ disk_01 │
│ all_2_2_0 │ disk_02 │
└───────────┴───────────┘
##由于max_data_part_size_bytes配置是1M,写⼊⼀个超过1M⼤⼩的分区
localhost :) INSERT INTO htc_table_1 SELECT rand() FROM numbers(300000);
##可以看到第三个分区被写⼊到clod_disk
localhost :) SELECT name, disk_name FROM system.parts WHERE table='htc_table_1';
┌─name──────┬─disk_name─┐
│ all_1_1_0 │ disk_01 │
│ all_2_2_0 │ disk_02 │
│ all_3_3_0 │ clod_disk │
└───────────┴───────────┘
HOT/COLD策略,由多个disk组成volume组。
每当⼀个新数据分区⽣成的时候,按照阈值(max_data_part_size_bytes)的⼤⼩,分区⽬录会按照volume组中定义的顺序依次写⼊。
合并分区或者⼀次性写⼊的分区⼤⼩超过max_data_part_size_bytes,也会被写⼊到COLD卷中。
分区移动
虽然MergeTree定义完存储策略后不能修改,但却可以移动分区
## 将某个分区移动到当前volume的另⼀个disk
localhost :) ALTER TABLE htc_table_1 MOVE PART 'all_1_1_0' TO DISK 'disk_02';
localhost :) SELECT name, disk_name FROM system.parts WHERE table='htc_table_1';
┌─name──────┬─disk_name─┐
│ all_1_1_0 │ disk_02 │
│ all_2_2_0 │ disk_02 │
│ all_3_3_0 │ clod_disk │
└───────────┴───────────┘
##将某个分区移动到其他volume
localhost :) ALTER TABLE htc_table_1 MOVE PART 'all_1_1_0' TO VOLUME 'cold_volume';
localhost :) SELECT name, disk_name FROM system.parts WHERE table='htc_table_1';
┌─name──────┬─disk_name─┐
│ all_1_1_0 │ clod_disk │
│ all_2_2_0 │ disk_02 │
│ all_3_3_0 │ clod_disk │
└───────────┴───────────┘。