文章目录
一、配置多磁盘存储
默认情况下,我们会子在配置文件config.xml文件中指定的
从19.15版本开始,ck开始支持多卷存储的功能,我们可以将数据存储在不同的存储设备中,多卷存储的实现有着很多的优势,如:
- 冷热数据分层存储
- 单节点存储能力提升
- 多存储设备之间可进行数据迁移
- 提高CK服务的整体IO性能
1、默认情况下,ck单磁盘存储
mdw :) select * from system.disks
SELECT *
FROM system.disks
┌─name────┬─path──────────────────────────┬──free_space─┬─total_space─┬─keep_free_space─┬─type──┐
│ default │ /data/clickhouse-server/data/ │ 16437395456 │ 42927656960 │ 0 │ local │
└─────────┴───────────────────────────────┴─────────────┴─────────────┴─────────────────┴───────┘
1 rows in set. Elapsed: 0.006 sec.
2、配置多磁盘
可以在config.d目录下创建storage.xml文件来单独配置存储信息,具体配置信息如下:
- default为默认数据目录
- 可自定义新增多个${disk_name},通过path为其定义具体的磁盘挂载目录
- 修改磁盘存储配置信息后,可登录ck服务查询system.disks表查看具体信息
[root@mdw config.d]# cat storage.xml
<yandex>
<storage_configuration>
<disks>
<default> <!-- default为默认的数据存储磁盘 -->
<keep_free_space_bytes>1024</keep_free_space_bytes>
</default>
<sansi_disk1> <!-- 自定义磁盘1,path指定挂载目录 -->
<path>/data1/</path>
</sansi_disk1>
<sansi_disk2> <!-- 自定义磁盘2,path指定挂载目录 -->
<path>/data2/</path>
</sansi_disk2>
</disks>
</storage_configuration>
</yandex>
3、多磁盘系统信息查询
设置多卷存储后,检查ck服务拉取到的磁盘信息
mdw :) select * from system.disks
SELECT *
FROM system.disks
┌─name────────┬─path──────────────────────────┬──free_space─┬─total_space─┬─keep_free_space─┬─type──┐
│ default │ /data/clickhouse-server/data/ │ 16622402560 │ 42927655936 │ 1024 │ local │
│ sansi_disk1 │ /data1/ │ 10692100096 │ 10725883904 │ 0 │ local │
│ sansi_disk2 │ /data2/ │ 10692100096 │ 10725883904 │ 0 │ local │
└─────────────┴───────────────────────────────┴─────────────┴─────────────┴─────────────────┴───────┘
3 rows in set. Elapsed: 0.014 sec.
二、配置多磁盘策略
ck配置多卷存储后,数据还是仍然无法使用到多个磁盘,如果需要将数据写入到多磁盘下,需要我们配置具体的磁盘策略,在创建表结构时指定具体的磁盘策略进行路由存储。
1、默认磁盘存储策略
mdw :) select * from system.storage_policies
SELECT *
FROM system.storage_policies
┌─policy_name─┬─volume_name─┬─volume_priority─┬─disks───────┬─volume_type─┬─max_data_part_size─┬─move_factor─┐
│ default │ default │ 1 │ ['default'] │ JBOD │ 0 │ 0 │
└─────────────┴─────────────┴─────────────────┴─────────────┴─────────────┴────────────────────┴─────────────┘
1 rows in set. Elapsed: 0.007 sec.
2、配置多磁盘存储策略
- policies中可定义一个或多个磁盘存储策略
- 需要在具体存储策略中定义需要将数据路由存储的磁盘名(disks中定义的磁盘名称)
- 磁盘存储策略可定义单磁盘存储或多磁盘存储
[root@mdw config.d]# cat storage.xml
<yandex>
<storage_configuration>
<disks>
<default>
<keep_free_space_bytes>1024</keep_free_space_bytes>
</default>
<sansi_disk1>
<path>/data1/</path>
</sansi_disk1>
<sansi_disk2>
<path>/data2/</path>
</sansi_disk2>
</disks>
<policies>
<disk1_only> <!-- 存储策略1,单磁盘存储 -->
<volumes>
<disk1_volume> <!-- 存储逻辑卷名称 -->
<disk>sansi_disk1</disk> <!-- 磁盘1 -->
</disk1_volume>
</volumes>
</disk1_only>
<disk1_disk2> <!-- 存储策略2,多磁盘存储-->
<volumes>
<disk1_disk2_volume> <!-- 存储逻辑卷名称 -->
<disk>sansi_disk1</disk> <!-- 磁盘1 -->
<disk>sansi_disk2</disk> <!-- 磁盘2 -->
</disk1_disk2_volume>
</volumes>
</disk1_disk2>
</storage_configuration>
</yandex>
3、磁盘存储策略系统信息查询
设置多存储存储策略后,可通过system.storage_policies表查询ck服务的具体信息
mdw :) select * from system.storage_policies
SELECT *
FROM system.storage_policies
┌─policy_name─┬─volume_name────────┬─volume_priority─┬─disks─────────────────────────┬─volume_type─┬─max_data_part_size─┬─move_factor─┐
│ default │ default │ 1 │ ['default'] │ JBOD │ 0 │ 0 │
│ disk1_disk2 │ disk1_disk2_volume │ 1 │ ['sansi_disk1','sansi_disk2'] │ JBOD │ 0 │ 0.1 │
│ disk1_only │ disk1_volume │ 1 │ ['sansi_disk1'] │ JBOD │ 0 │ 0.1 │
└─────────────┴────────────────────┴─────────────────┴───────────────────────────────┴─────────────┴────────────────────┴─────────────┘
3 rows in set. Elapsed: 0.011 sec.
三、多磁盘存储使用
1、多磁盘存储表
- 多磁盘存储策略需要在建表时通过settings storage_policy='xxx’指定
- 可通过show create table xxx、system.tables表来查看指定表的磁盘存储策略
- 表数据存储是根据分区的粒度进行存储的,可通过system.parts系统表来查看表分区存储位置
1)创建表结构,分为创建t1表使用多磁盘存储策略,t2表使用单磁盘存储,t3表使用默认存储策略。
mdw :) create table t1(`id` Int32,`name` String) engine=MergeTree() order by id settings storage_policy='disk1_disk2';
mdw :) create table t2(`id` Int32,`name` String) engine=MergeTree() order by id settings storage_policy='disk1_disk2';
mdw :) create table t3(`id` Int32,`name` String) engine=MergeTree() order by id;
2)模拟数据写入
mdw :) insert into t1 values(1,'aa'),(2,'bb'),(3,'cc');
mdw :) insert into t2 values(1,'aa'),(2,'bb'),(3,'cc');
mdw :) insert into t3 values(1,'aa'),(2,'bb'),(3,'cc');
3)查看表数据磁盘分布
mdw :) SELECT name, data_paths, metadata_path, storage_policy from system.tables where name in ('t1','t2','t3')
SELECT
name,
data_paths,
metadata_path,
storage_policy
FROM system.tables
WHERE name IN ('t1', 't2', 't3')
┌─name─┬─data_paths────────────────────────────────────┬─metadata_path────────────────────────────────────┬─storage_policy─┐
│ t1 │ ['/data1/data/db1/t1/'] │ /data/clickhouse-server/data/metadata/db1/t1.sql │ disk1_only │
│ t2 │ ['/data1/data/db1/t2/','/data2/data/db1/t2/'] │ /data/clickhouse-server/data/metadata/db1/t2.sql │ disk1_disk2 │
│ t3 │ ['/data/clickhouse-server/data/data/db1/t3/'] │ /data/clickhouse-server/data/metadata/db1/t3.sql │ default │
└──────┴───────────────────────────────────────────────┴──────────────────────────────────────────────────┴────────────────┘
3 rows in set. Elapsed: 0.009 sec.
2、多磁盘数据迁移
- CK表根据分区粒度存储在指定的存储磁盘目录下
- 当表分区发生合并时,ck会自动将需要合并的分区进行合并,并统一存储在其中某一分区下
- 表分区合并可能会造成各个磁盘目录实际使用空间大小不均衡
- 磁盘存储策略move_factor设置默认为0.1,表示当一个磁盘卷可用空间不足10%时,ck会后台尝试通过将不足空间中的 part 移动到下一个磁盘卷来释放空间。
- 可设置move_factor为0,表示禁止后台对分区的移动,当时生产环境不建议这样操作
1)创建一个多磁盘存储策略的表,使用策略disk1_disk2,表示数据会存储在/data1、/data2下。
mdw :) create table t4(id UInt64) ENGINE = MergeTree() ORDER BY id SETTINGS storage_policy = 'disk1_disk2';
mdw :) insert into t4 select * from numbers(1000000);
mdw :) insert into t4 select * from numbers(1000000);
mdw :) insert into t4 select * from numbers(1000000);
mdw :) insert into t4 select * from numbers(1000000);
2)查看表数据和分区存储信息,可以看到按照分区将数据写入到了不同的磁盘目录下
mdw :) SELECT name, data_paths, metadata_path, storage_policy from system.tables where name ='t4'
SELECT
name,
data_paths,
metadata_path,
storage_policy
FROM system.tables
WHERE name = 't4'
┌─name─┬─data_paths────────────────────────────────────┬─metadata_path────────────────────────────────────┬─storage_policy─┐
│ t4 │ ['/data1/data/db1/t4/','/data2/data/db1/t4/'] │ /data/clickhouse-server/data/metadata/db1/t4.sql │ disk1_disk2 │
└──────┴───────────────────────────────────────────────┴──────────────────────────────────────────────────┴────────────────┘
1 rows in set. Elapsed: 0.007 sec.
mdw :) select name, disk_name, path from system.parts where table = 't4';
SELECT
name,
disk_name,
path
FROM system.parts
WHERE table = 't4'
┌─name──────┬─disk_name───┬─path──────────────────────────┐
│ all_1_1_0 │ sansi_disk1 │ /data1/data/db1/t4/all_1_1_0/ │
│ all_2_2_0 │ sansi_disk2 │ /data2/data/db1/t4/all_2_2_0/ │
│ all_3_3_0 │ sansi_disk1 │ /data1/data/db1/t4/all_3_3_0/ │
│ all_4_4_0 │ sansi_disk2 │ /data2/data/db1/t4/all_4_4_0/ │
└───────────┴─────────────┴───────────────────────────────┘
4 rows in set. Elapsed: 0.007 sec.
3)手动模拟分区合并,分区合并会自动将其他磁盘目录下数据进行合并,并存储在其中某一磁盘下。
mdw :) optimize table t4;
OPTIMIZE TABLE t4
Ok.
0 rows in set. Elapsed: 0.216 sec.
mdw :) select name, disk_name, path from system.parts where table = 't4' and active;
SELECT
name,
disk_name,
path
FROM system.parts
WHERE (table = 't4') AND active
┌─name──────┬─disk_name───┬─path──────────────────────────┐
│ all_1_4_1 │ sansi_disk1 │ /data1/data/db1/t4/all_1_4_1/ │
└───────────┴─────────────┴───────────────────────────────┘
1 rows in set. Elapsed: 0.009 sec.
4)再次模拟数据写入
mdw :) insert into t4 select * from numbers(1000000);
mdw :) insert into t4 select * from numbers(1000000);
mdw :) insert into t4 select * from numbers(1000000);
mdw :) select name, disk_name, path from system.parts where table = 't4' and active;
SELECT
name,
disk_name,
path
FROM system.parts
WHERE (table = 't4') AND active
┌─name──────┬─disk_name───┬─path──────────────────────────┐
│ all_1_4_1 │ sansi_disk1 │ /data1/data/db1/t4/all_1_4_1/ │
│ all_5_5_0 │ sansi_disk2 │ /data2/data/db1/t4/all_5_5_0/ │
│ all_6_6_0 │ sansi_disk1 │ /data1/data/db1/t4/all_6_6_0/ │
│ all_7_7_0 │ sansi_disk2 │ /data2/data/db1/t4/all_7_7_0/ │
└───────────┴─────────────┴───────────────────────────────┘
4 rows in set. Elapsed: 0.008 sec.
5)多磁盘分区迁移
基本语法
ALTER TABLE sample4 MOVE PART 'all_570_570_0' TO VOLUME 'cold_volume'
ALTER TABLE sample4 MOVE PART 'all_570_570_0' TO DISK 'ebs_gp2_1'
ALTER TABLE sample4 MOVE PARTITION tuple() TO VOLUME 'cold_volume'
示例
mdw :) select name, disk_name, path from system.parts where table = 't4' and active;
SELECT
name,
disk_name,
path
FROM system.parts
WHERE (table = 't4') AND active
┌─name──────┬─disk_name───┬─path──────────────────────────┐
│ all_1_4_1 │ sansi_disk1 │ /data1/data/db1/t4/all_1_4_1/ │
│ all_5_5_0 │ sansi_disk2 │ /data2/data/db1/t4/all_5_5_0/ │
│ all_6_6_0 │ sansi_disk1 │ /data1/data/db1/t4/all_6_6_0/ │
│ all_7_7_0 │ sansi_disk2 │ /data2/data/db1/t4/all_7_7_0/ │
└───────────┴─────────────┴───────────────────────────────┘
4 rows in set. Elapsed: 0.008 sec.
mdw :) select * from system.storage_policies
SELECT *
FROM system.storage_policies
┌─policy_name─┬─volume_name────────┬─volume_priority─┬─disks─────────────────────────┬─volume_type─┬─max_data_part_size─┬─move_factor─┐
│ default │ default │ 1 │ ['default'] │ JBOD │ 0 │ 0 │
│ disk1_disk2 │ disk1_disk2_volume │ 1 │ ['sansi_disk1','sansi_disk2'] │ JBOD │ 0 │ 0.1 │
│ disk1_only │ disk1_volume │ 1 │ ['sansi_disk1'] │ JBOD │ 0 │ 0.1 │
└─────────────┴────────────────────┴─────────────────┴───────────────────────────────┴─────────────┴────────────────────┴─────────────┘
3 rows in set. Elapsed: 0.006 sec.
mdw :) alter table t4 move part 'all_6_6_0' to disk 'sansi_disk2';
ALTER TABLE t4
MOVE PART 'all_6_6_0' TO DISK 'sansi_disk2'
Ok.
0 rows in set. Elapsed: 0.076 sec.
mdw :) select name, disk_name, path from system.parts where table = 't4' and active;
SELECT
name,
disk_name,
path
FROM system.parts
WHERE (table = 't4') AND active
┌─name──────┬─disk_name───┬─path──────────────────────────┐
│ all_1_4_1 │ sansi_disk1 │ /data1/data/db1/t4/all_1_4_1/ │
│ all_5_5_0 │ sansi_disk2 │ /data2/data/db1/t4/all_5_5_0/ │
│ all_6_6_0 │ sansi_disk2 │ /data2/data/db1/t4/all_6_6_0/ │
│ all_7_7_0 │ sansi_disk2 │ /data2/data/db1/t4/all_7_7_0/ │
└───────────┴─────────────┴───────────────────────────────┘
4 rows in set. Elapsed: 0.011 sec.
参考文档:
https://blog.csdn.net/jiangshouzhuang/article/details/103650360