一、分區設計
1.使用類型
1)不指定分區鍵
如果建表時不指定分區鍵,則數據默認不分區,所有數據寫到一個默認分區all里面。
2)使用整型
如果分區鍵取值屬於整型且無法轉換為日期類型YYYVYMMDD格式,則直接按照該整型的字符形式輸出作為分區ID的取值。
3)使用日期類型
如果分區鍵取值屬於日期類型,或者是能夠轉換為YYYYMMDD日期格式的整型,則按照分區表達式邏輯格式化后作為分區ID的取值。
4)使用其它類型
如果分區鍵取值既不屬於整型,也不屬於日期類型,例如String、Float等,則通過128位Hash算法取其Hash值作為分區ID的取值。
(默認情況下,不支持浮點分區鍵。要使用它,請啟用設置allow_floating_point_partition_key。)
5)使用tuple元組類型
分區鍵也可以是表達式的元組(類似於主鍵)
ENGINE = ReplicatedCollapsingMergeTree('/clickhouse/tables/name', 'replica1', Sign) PARTITION BY (toMonday(StartDate), EventType) ORDER BY (CounterID, StartDate, intHash32(UserID));
2.分區目錄命名規則
20220124_1_1_0_[11]
20220123_1_2_0
partition_id_ min_block_number_ max_block _number_ level [_version]
!!!舊類型表的部分具有以下名稱:(20220117_20220123_2_2_0
最小日期 - 最大日期 - 最小塊數 - 最大塊數 - 級別)。
1)partition_id:20220124,分區生成規則見上;
2)min_block_number:1,最小塊編號,MergeTree引|擎從1開始計數,每次+1;
3)max block_number:1,最大塊編號,新插入的數據,最小與最大編號一致;
4)level:0,這個可以理解為合並的次數,新插入的數據都是0,每合並1次+1。
5)mutation version:11
是突變版本(如果部分突變)。[並非所有都帶有突變]
3.分區目錄合並過程
如圖:
向表中插入新數據時,此數據存儲為按主鍵排序的單獨部分(塊)。插入后10-15分鍾,同一分區的部分合並為整個部分。
!!!合並僅適用於分區表達式具有相同值的數據部分。這意味着不應該制作過於精細的分區(超過大約一千個分區)。否則,SELECT
由於文件系統中的文件數量過多以及打開的文件描述符,查詢性能會很差。
使用system.parts表查看表部分和分區。例如,假設我們有一個visits
按月分區的表。讓我們對表執行SELECT
查詢system.parts
:
SELECT partition, name, active FROM system.parts WHERE table = 'visits' and database ='test';
┌─partition─┬─name──────────────┬─active─┐ │ 202201 │ 202201_1_3_1 │ 0 │ │ 202201 │ 202201_1_9_2_11 │ 1 │ │ 202201 │ 202201_8_8_0 │ 0 │ │ 202201 │ 202201_9_9_0 │ 0 │ │ 202202 │ 202202_4_6_1_11 │ 1 │ │ 202202 │ 202202_10_10_0_11 │ 1 │ │ 202202 │ 202202_11_11_0_11 │ 1 │ └───────────┴───────────────────┴────────┘
該active
列顯示部件的狀態。1
活躍; 0
處於非活動狀態。例如,非活動部分是合並到較大部分后剩余的源部分。損壞的數據部分也被指示為非活動的。
同一分區有多個獨立的部分(例如,202201_1_3_1
和202201_1_9_2
)。這意味着這些部分尚未合並。ClickHouse 會定期合並插入的部分數據,大約在插入后 15 分鍾。此外,可以使用OPTIMIZE查詢執行非計划合並。
合並后大約 10 分鍾將刪除不活動的部分。
4.分區設計
分區選擇考慮merge (寫入放大)、查詢(slelect part數量)、啟動等方面考慮。在實際生產中選擇時間作為分區鍵,根據表數據的大小按天或者按周進行了分區。
如圖:
二、分區操作
分區操作
- DETACH PARTITION - 將分區移動到
detached
目錄並忘記它。 - DROP PARTITION — 刪除分區。
- ATTACH PART|PARTITION — 將
detached
目錄中的數據塊或分區添加到表中。 - ATTACH PARTITION FROM — 將數據分區從一個表復制到另一個表並添加。
- REPLACE PARTITION — 將數據分區從一個表復制到另一個表並替換。
- MOVE PARTITION TO TABLE — 將數據分區從一個表移動到另一個表。
- CLEAR COLUMN IN PARTITION — 重置分區中指定列的值。
- CLEAR INDEX IN PARTITION — 重置分區中指定的二級索引。
- FREEZE PARTITION — 創建分區的備份。
- UNFREEZE PARTITION — 刪除分區的備份。
- FETCH PARTITION|PART — 從另一台服務器下載數據塊或分區。
- MOVE PARTITION|PART — 將分區/數據塊移動到另一個磁盤或卷。
- UPDATE IN PARTITION — 按條件更新分區內的數據。
- DELETE IN PARTITION — 按條件刪除分區內的數據。
DETACH PARTITION|PART
ALTER TABLE table_name DETACH PARTITION|PART partition_expr
將指定分區的所有數據移動到detached
目錄中。服務器忘記了分離的數據分區,就好像它不存在一樣。在進行ATTACH查詢之前,服務器不會知道此數據。
例子:
ALTER TABLE mt DETACH PARTITION '2020-11-21'; ALTER TABLE mt DETACH PART 'all_2_2_0';
執行查詢后,你可以對detached
目錄中的數據做任何你想做的事情——從文件系統中刪除它,或者直接離開它。
此查詢被復制——它將數據移動到detached
所有副本上的目錄。請注意,只能在領導者副本上執行此查詢。要確定副本是否是領導者,請對system.replicas表執行SELECT
查詢。或者,對所有副本進行查詢更容易- 所有副本都拋出異常,除了領導者副本(因為允許多個領導者)。DETACH
DROP PARTITION|PART
ALTER TABLE table_name DROP PARTITION|PART partition_expr
從表中刪除指定的分區。此查詢將分區標記為非活動並完全刪除數據,大約在 10 分鍾內。
查詢被復制——它刪除所有副本上的數據。
例子:
ALTER TABLE mt DROP PARTITION '2020-11-21'; ALTER TABLE mt DROP PART 'all_4_4_0';
DROP DETACHED PARTITION|PART
ALTER TABLE table_name DROP DETACHED PARTITION|PART partition_expr
從 中刪除指定分區的指定數據塊或所有數據塊detached
。
ATTACH PARTITION|PART
ALTER TABLE table_name ATTACH PARTITION|PART partition_expr
將數據從detached
目錄添加到表中。可以為整個分區或單獨的數據塊添加數據。例子:
ALTER TABLE visits ATTACH PARTITION 201901; ALTER TABLE visits ATTACH PART 201901_2_2_0;
此查詢被復制。副本發起者檢查目錄中是否有數據detached
。如果數據存在,則查詢檢查其完整性。如果一切正確,則查詢將數據添加到表中。
如果接收到附加命令的非發起者副本在其自己的detached
文件夾中找到具有正確校驗和的數據塊,它會附加數據而不從其他副本中獲取數據。如果沒有具有正確校驗和的零件,則從具有該零件的任何副本下載數據。
可以將數據detached
放在一個副本上的目錄中,並使用ALTER ... ATTACH
查詢將其添加到所有副本上的表中。
ATTACH PARTITION FROM
ALTER TABLE table2 ATTACH PARTITION partition_expr FROM table1
此查詢將數據分區從 復制table1
到table2
。請注意,既不會從table1
也不會從中刪除數據table2
。
要使查詢成功運行,必須滿足以下條件:
- 兩個表必須具有相同的結構。
- 兩個表必須具有相同的分區鍵。
REPLACE PARTITION
ALTER TABLE table2 REPLACE PARTITION partition_expr FROM table1
此查詢將數據分區從 復制table1
到table2
並替換 中的現有分區table2
。請注意,數據不會從table1
.
要使查詢成功運行,必須滿足以下條件:
- 兩個表必須具有相同的結構。
- 兩個表必須具有相同的分區鍵。
MOVE PARTITION TO TABLE
ALTER TABLE table_source MOVE PARTITION partition_expr TO TABLE table_dest
此查詢將數據分區從 移動table_source
到,並從 中table_dest
刪除數據table_source
。
要使查詢成功運行,必須滿足以下條件:
- 兩個表必須具有相同的結構。
- 兩個表必須具有相同的分區鍵。
- 兩個表必須是相同的引擎系列(復制或非復制)。
- 兩個表必須具有相同的存儲策略。
CLEAR COLUMN IN PARTITION
ALTER TABLE table_name CLEAR COLUMN column_name IN PARTITION partition_expr
重置分區中指定列中的所有值。如果DEFAULT
在創建表時確定了該子句,則此查詢將列值設置為指定的默認值。
例子:
ALTER TABLE visits CLEAR COLUMN hour in PARTITION 201902
FREEZE PARTITION
ALTER TABLE table_name FREEZE [PARTITION partition_expr] [WITH NAME 'backup_name']
此查詢創建指定分區的本地備份。如果PARTITION
省略該子句,則查詢會立即創建所有分區的備份。
!!!note "注意" 整個備份過程在不停止服務器的情況下執行。
對於舊式表,可以指定分區名稱的前綴(例如,2019
) - 然后查詢會為所有相應的分區創建備份。
在執行時,對於數據快照,查詢會創建指向表數據的硬鏈接。硬鏈接放置在目錄/var/lib/clickhouse/shadow/N/...
中,其中:
/var/lib/clickhouse/
是配置中指定的工作 ClickHouse 目錄。N
是備份的增量數。- 如果
WITH NAME
指定了'backup_name'
參數,則使用參數的值而不是增量數。
!!!“注意” 如果使用一組磁盤存儲表中的數據,則shadow/N
目錄會出現在每個磁盤上,存儲PARTITION
表達式匹配的數據數據塊。
在備份內部創建與 inside 相同的目錄結構/var/lib/clickhouse/
。查詢chmod
對所有文件執行,禁止寫入它們。
創建備份后,可以將數據從遠程服務器復制/var/lib/clickhouse/shadow/
到遠程服務器,然后將其從本地服務器中刪除。請注意,ALTER t FREEZE PARTITION
查詢不會被復制。它僅在本地服務器上創建本地備份。
該查詢幾乎立即創建備份(但首先它等待對相應表的當前查詢完成運行)。
ALTER TABLE t FREEZE PARTITION
只復制數據,不復制表元數據。要備份表元數據,請復制文件/var/lib/clickhouse/metadata/database/table.sql
要從備份中恢復數據,請執行以下操作:
- 如果表不存在,則創建它。要查看查詢,請使用 .sql 文件(
ATTACH
在其中替換為CREATE
)。 data/database/table/
將備份中的目錄中的數據復制到/var/lib/clickhouse/data/database/table/detached/
目錄中。- 運行
ALTER TABLE t ATTACH PARTITION
查詢以將數據添加到表中。
從備份恢復不需要停止服務器。
UNFREEZE PARTITION
ALTER TABLE 'table_name' UNFREEZE [PARTITION 'part_expr'] WITH NAME 'backup_name'
從磁盤中刪除freezed
具有指定名稱的分區。如果PARTITION
省略該子句,則查詢會立即刪除所有分區的備份。
CLEAR INDEX IN PARTITION
ALTER TABLE table_name CLEAR INDEX index_name IN PARTITION partition_expr
該查詢的工作方式類似於CLEAR COLUMN
,但它重置索引而不是列數據。
FETCH PARTITION|PART
ALTER TABLE table_name FETCH PARTITION|PART partition_expr FROM 'path-in-zookeeper'
從另一台服務器下載分區。此查詢僅適用於復制的表。
查詢執行以下操作:
- 從指定的分片下載分區|數據塊。在“path-in-zookeeper”中,必須指定 ZooKeeper 中分片的路徑。
- 然后查詢把下載的數據放到表的
detached
目錄下table_name
。使用ATTACH PARTITION|PART查詢將數據添加到表中。
例如:
- 獲取分區
ALTER TABLE users FETCH PARTITION 201902 FROM '/clickhouse/tables/01-01/visits'; ALTER TABLE users ATTACH PARTITION 201902;
- 獲取數據塊
ALTER TABLE users FETCH PART 201901_2_2_0 FROM '/clickhouse/tables/01-01/visits'; ALTER TABLE users ATTACH PART 201901_2_2_0;
注意:
- 查詢不會被
ALTER ... FETCH PARTITION|PART
復制。它僅將部件或分區detached
放置到本地服務器上的目錄中。 - 查詢被
ALTER TABLE ... ATTACH
復制。它將數據添加到所有副本。數據從detached
目錄添加到其中一個副本,並從相鄰副本添加到其他副本。
在下載之前,系統會檢查分區是否存在以及表結構是否匹配。從健康的副本中自動選擇最合適的副本。
雖然調用了查詢ALTER TABLE
,但它不會更改表結構,也不會立即更改表中可用的數據。
MOVE PARTITION|PART
將分區或數據塊移動到另一個卷或磁盤以用於MergeTree
-engine 表。
ALTER TABLE table_name MOVE PARTITION|PART partition_expr TO DISK|VOLUME 'disk_name'
ALTER TABLE t MOVE
查詢:
- 不復制,因為不同的副本可以有不同的存儲策略。
- 如果未配置指定的磁盤或卷,則返回錯誤。如果存儲策略中指定的數據移動條件無法應用,查詢也會返回錯誤。
- 在要移動的數據已被后台進程、並發
ALTER TABLE t MOVE
查詢或后台數據合並的結果移動的情況下,可以返回錯誤。在這種情況下,用戶不應執行任何其他操作。
例子:
ALTER TABLE hits MOVE PART '20190301_14343_16206_438' TO VOLUME 'slow' ALTER TABLE hits MOVE PARTITION '2019-09-01' TO DISK 'fast_ssd'
UPDATE IN PARTITION
操作與指定過濾表達式匹配的指定分區中的數據。作為一個突變實現。
句法:
ALTER TABLE [db.]table UPDATE column1 = expr1 [, ...] [IN PARTITION partition_id] WHERE filter_expr
例子
ALTER TABLE mt UPDATE x = x + 1 IN PARTITION 2 WHERE p = 2;
DELETE IN PARTITION
刪除與指定過濾表達式匹配的指定分區中的數據。作為一個突變實現。
句法:
ALTER TABLE [db.]table DELETE [IN PARTITION partition_id] WHERE filter_expr
例子
ALTER TABLE mt DELETE IN PARTITION 2 WHERE p = 2;
三、分區優化
1)分區粒度根據業務特點決定,不宜過粗或過細。一般選擇按天分區,也可以指定為Tuple(),以單表一億數據為例,分區大小控制在10-30個為最佳。
2)那些有相同分區表達式值的數據片段才會合並。這意味着 你不應該用太精細的分區方案(超過一千個分區)。否則,會因為文件系統中的文件數量過多和需要打開的文件描述符過多,導致 SELECT 查詢效率不佳。
3)還有就是一般我們都是使用的是日期作為分區鍵,同一分區內有序,不同分區不能保證有序。