天天看點

Clickhouse多磁盤存儲一、配置多磁盤存儲二、配置多磁盤政策三、多磁盤存儲使用

文章目錄

  • 一、配置多磁盤存儲
    • 1、預設情況下,ck單磁盤存儲
    • 2、配置多磁盤
    • 3、多磁盤系統資訊查詢
  • 二、配置多磁盤政策
    • 1、預設磁盤存儲政策
    • 2、配置多磁盤存儲政策
    • 3、磁盤存儲政策系統資訊查詢
  • 三、多磁盤存儲使用
    • 1、多磁盤存儲表
    • 2、多磁盤資料遷移

一、配置多磁盤存儲

預設情況下,我們會子在配置檔案config.xml檔案中指定的

xxx/

目錄為我們的資料目錄,該磁盤在ck中為default儲存設備。所有的建表、資料寫入預設都寫入到我們指定的default目錄下。

從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表檢視具體資訊
[[email protected] 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中定義的磁盤名稱)
  • 磁盤存儲政策可定義單磁盤存儲或多磁盤存儲
[[email protected] 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