clickhouse的多路徑存儲策略


個人學習筆記,謝絕轉載!!!

原文:https://www.cnblogs.com/wshenjin/p/14583918.html


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   │
│ disk_01 │ /data/chbase/data_01/           │ 13.19 GiB │ 29.98 GiB │ 0.00 B   │
│ disk_02 │ /data/chbase/data_02/           │ 13.19 GiB │ 29.98 GiB │ 0.00 B   │
│ disk_03 │ /data/chbase/data_03/           │ 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──┐
│ clod_disk │ /data/chbase/cold_data/         │ 29.94 GiB │ 29.97 GiB │ 20.00 GiB │
│ default   │ /data/database/clickhouse/data/ │ 16.49 GiB │ 27.94 GiB │ 0.00 B    │
│ disk_01   │ /data/chbase/data_01/           │ 9.96 GiB  │ 9.99 GiB  │ 0.00 B    │
│ 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 │
└───────────┴───────────┘


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM