修改表
修改表名
-- 1.將名為 table1 的表修改為 table2
ALTER TABLE table1 RENAME table2;
-- 示例
ALTER TABLE aggregate_test RENAME aggregate_test1;
-- 2.將表 example_table 中名為 rollup1 的 rollup index 修改為 rollup2
ALTER TABLE base_table_name RENAME ROLLUP old_rollup_name new_rollup_name;
ALTER TABLE ex_user RENAME ROLLUP rollup_u_cost new_rollup_u_cost;
desc ex_user all;
-- 3.將表 example_table 中名為 p1 的 partition 修改為 p2
ALTER TABLE example_table RENAME PARTITION old_partition_name new_partition_name ;
-- 示例:
ALTER TABLE expamle_range_tbl RENAME PARTITION p201701 newp201701;
show partitions from expamle_range_tbl \G;
表結(jié)構(gòu)變更
用戶(hù)可以通過(guò) Schema Change 操作來(lái)修改已存在表的 Schema。目前 Doris 支持以下幾種修改:
? 增加、刪除列
? 修改列類(lèi)型
? 調(diào)整列順序
? 增加、修改 Bloom Filter index
? 增加、刪除 bitmap index
原理介紹
執(zhí)行 Schema Change 的基本過(guò)程,是通過(guò)原 Index 的數(shù)據(jù),生成一份新 Schema 的 Index 的數(shù)據(jù)。其中主要需要進(jìn)行兩部分?jǐn)?shù)據(jù)轉(zhuǎn)換:
一是已存在的歷史數(shù)據(jù)的轉(zhuǎn)換;
二是在 Schema Change 執(zhí)行過(guò)程中,新到達(dá)的導(dǎo)入數(shù)據(jù)的轉(zhuǎn)換。
創(chuàng)建作業(yè)
Schema Change 的創(chuàng)建是一個(gè)異步過(guò)程,作業(yè)提交成功后,用戶(hù)需要通過(guò) SHOW ALTER TABLE COLUMN 命令來(lái)查看作業(yè)進(jìn)度。
-- 語(yǔ)法:
ALTER TABLE [database.]table alter_clause;
schema change 的 alter_clause 支持如下幾種修改方式:
1.向指定 index 的指定位置添加一列
ALTER TABLE db.table_name
-- 如果增加的是key列 那么,需要在 列類(lèi)型后面增加key 這個(gè)關(guān)鍵字
-- 如果增加的是value列 那么,是聚合表模型,需要指定列的聚合類(lèi)型 如果是明細(xì)模型和唯一模型,不需要指定
ADD COLUMN column_name column_type [KEY | agg_type] [DEFAULT "default_value"]
[AFTER column_name|FIRST] -- 確定列的位置 如果不寫(xiě),默認(rèn)插在最后
[TO rollup_index_name] -- 如果你是針對(duì)rollup表新增一個(gè)列,那么這個(gè)列明基表中不能有
[PROPERTIES ("key"="value", ...)]
-- 明細(xì)模型中添加value列
ALTER TABLE test.expamle_range_tbl ADD COLUMN abc varchar AFTER age;
-- 明細(xì)模型中添加key 列
ALTER TABLE test.expamle_range_tbl ADD COLUMN abckey varchar key AFTER user_id;
-- 聚合模型中添加一個(gè)value列
mysql> ALTER TABLE test.ex_user ADD COLUMN abckey int sum AFTER cost;
注意:
- 聚合模型如果增加 value 列,需要指定 agg_type
- 非聚合模型(如 DUPLICATE KEY)如果增加key列,需要指定KEY關(guān)鍵字
- 不能在 rollup index 中增加 base index 中已經(jīng)存在的列(如有需要,可以重新創(chuàng)建一個(gè) rollup index)
示例:
-- 源schema:
+-----------+-------+------+------+------+---------+-------+
| IndexName | Field | Type | Null | Key | Default | Extra |
+-----------+-------+------+------+------+---------+-------+
| tbl1 | k1 | INT | No | true | N/A | |
| | k2 | INT | No | true | N/A | |
| | k3 | INT | No | true | N/A | |
| | | | | | | |
| rollup2 | k2 | INT | No | true | N/A | |
| | | | | | | |
| rollup1 | k1 | INT | No | true | N/A | |
| | k2 | INT | No | true | N/A | |
+-----------+-------+------+------+------+---------+-------+
-- 源schema中沒(méi)有k4和k5列,所以可以往rollup表中添加 k4和k5列,在往rollup表中添加的過(guò)程,也會(huì)往base表中添加一份
ALTER TABLE tbl1
ADD COLUMN k4 INT default "1" to rollup1,
ADD COLUMN k4 INT default "1" to rollup2,
ADD COLUMN k5 INT default "1" to rollup2;
-- 改變完成后,Schema 變?yōu)? base表中也會(huì)相應(yīng)的添加k4和k5
+-----------+-------+------+------+------+---------+-------+
| IndexName | Field | Type | Null | Key | Default | Extra |
+-----------+-------+------+------+------+---------+-------+
| tbl1 | k1 | INT | No | true | N/A | |
| | k2 | INT | No | true | N/A | |
| | k3 | INT | No | true | N/A | |
| | k4 | INT | No | true | 1 | |
| | k5 | INT | No | true | 1 | |
| | | | | | | |
| rollup2 | k2 | INT | No | true | N/A | |
| | k4 | INT | No | true | 1 | |
| | k5 | INT | No | true | 1 | |
| | | | | | | |
| rollup1 | k1 | INT | No | true | N/A | |
| | k2 | INT | No | true | N/A | |
| | k4 | INT | No | true | 1 | |
+-----------+-------+------+------+------+---------+-------+
-- 這樣的導(dǎo)入方式錯(cuò)誤
-- 因?yàn)閎ase表中已經(jīng)存在k3,導(dǎo)入的時(shí)候無(wú)法將base表中在添加一個(gè)叫k3的列,重復(fù)
ALTER TABLE tbl1
ADD COLUMN k3 INT default "1" to rollup1
2.向指定 index 添加多列
ALTER TABLE db.table_name
ADD COLUMN (column_name1 column_type [KEY | agg_type] DEFAULT "default_value", ...)
[TO rollup_index_name]
[PROPERTIES ("key"="value", ...)]
-- 添加的時(shí)候根據(jù)key和value列,添加在對(duì)應(yīng)的列之后
ALTER TABLE test.expamle_range_tbl ADD COLUMN (abc int,bcd int);
mysql> ALTER TABLE test.expamle_range_tbl ADD COLUMN (a int key ,b int);
Query OK, 0 rows affected (0.01 sec)
mysql> desc expamle_range_tbl all;
3.從指定 index 中刪除一列
ALTER TABLE db.table_name
DROP COLUMN column_name
[FROM rollup_index_name]
-- 刪除明細(xì)表中的value列
ALTER TABLE test.expamle_range_tbl DROP COLUMN abc;
-- 刪除明細(xì)表中的key列
ALTER TABLE test.expamle_range_tbl DROP COLUMN abckey;
-- 刪除聚合模型中的value列
ALTER TABLE test.ex_user DROP COLUMN abckey;
-- 注意:
-- 不能刪除分區(qū)列
-- 如果是從 base index 中刪除列,則如果 rollup index 中包含該列,也會(huì)被刪除
4.修改指定 index 的列類(lèi)型以及列位置
ALTER TABLE db.table_name
MODIFY COLUMN column_name column_type [KEY | agg_type] [NULL | NOT NULL] [DEFAULT "default_value"]
[AFTER column_name|FIRST]
[FROM rollup_index_name]
[PROPERTIES ("key"="value", ...)]
-- 注意:
-- 聚合模型如果修改 value 列,需要指定 agg_type
-- 非聚合類(lèi)型如果修改key列,需要指定KEY關(guān)鍵字
-- 分區(qū)列和分桶列不能做任何修改
5.對(duì)指定 index 的列進(jìn)行重新排序
ALTER TABLE db.table_name
ORDER BY (column_name1, column_name2, ...)
[FROM rollup_index_name]
[PROPERTIES ("key"="value", ...)]
-- 注意:
-- index 中的所有列都要寫(xiě)出來(lái)
-- value 列在 key 列之后
示例:
-- 1.向 example_rollup_index 的 col1 后添加一個(gè)key列 new_col(非聚合模型)
ALTER TABLE example_db.my_table
ADD COLUMN new_col INT KEY DEFAULT "0" AFTER col1
TO example_rollup_index;
-- 2.向example_rollup_index的col1后添加一個(gè)value列new_col(非聚合模型)
ALTER TABLE example_db.my_table
ADD COLUMN new_col INT DEFAULT "0" AFTER col1
TO example_rollup_index;
-- 3.向example_rollup_index的col1后添加一個(gè)key列new_col(聚合模型)
ALTER TABLE example_db.my_table
ADD COLUMN new_col INT DEFAULT "0" AFTER col1
TO example_rollup_index;
-- 4.向example_rollup_index的col1后添加一個(gè)value列new_col SUM聚合類(lèi)型(聚合模型)
ALTER TABLE example_db.my_table
ADD COLUMN new_col INT SUM DEFAULT "0" AFTER col1
TO example_rollup_index;
-- 5.向 example_rollup_index 添加多列(聚合模型)
ALTER TABLE example_db.my_table
ADD COLUMN (col1 INT DEFAULT "1", col2 FLOAT SUM DEFAULT "2.3")
TO example_rollup_index;
-- 6.從 example_rollup_index 刪除一列
ALTER TABLE example_db.my_table
DROP COLUMN col2
FROM example_rollup_index;
-- 7.修改 base index 的 key 列 col1 的類(lèi)型為 BIGINT,并移動(dòng)到 col2 列后面。
ALTER TABLE example_db.my_table
MODIFY COLUMN col1 BIGINT KEY DEFAULT "1" AFTER col2;
-- 注意:無(wú)論是修改 key 列還是 value 列都需要聲明完整的 column 信息
-- 8.修改 base index 的 val1 列最大長(zhǎng)度。原 val1 為 (val1 VARCHAR(32) REPLACE DEFAULT "abc")
ALTER TABLE example_db.my_table
MODIFY COLUMN val1 VARCHAR(64) REPLACE DEFAULT "abc";
-- 9.重新排序 example_rollup_index 中的列(設(shè)原列順序?yàn)椋簁1,k2,k3,v1,v2)
ALTER TABLE example_db.my_table
ORDER BY (k3,k1,k2,v2,v1)
FROM example_rollup_index;
-- 10.同時(shí)執(zhí)行兩種操作
ALTER TABLE example_db.my_table
ADD COLUMN v2 INT MAX DEFAULT "0" AFTER k2 TO example_rollup_index,
ORDER BY (k3,k1,k2,v2,v1) FROM example_rollup_index;
查看作業(yè)
SHOW ALTER TABLE COLUMN 可以查看當(dāng)前正在執(zhí)行或已經(jīng)完成的 Schema Change 作業(yè)。當(dāng)一次 Schema Change 作業(yè)涉及到多個(gè) Index 時(shí),該命令會(huì)顯示多行,每行對(duì)應(yīng)一個(gè) Index
SHOW ALTER TABLE COLUMN\G;
*************************** 1. row ***************************
JobId: 20021
TableName: tbl1
CreateTime: 2019-08-05 23:03:13
FinishTime: 2019-08-05 23:03:42
IndexName: tbl1
IndexId: 20022
OriginIndexId: 20017
SchemaVersion: 2:792557838
TransactionId: 10023
State: FINISHED
Msg:
Progress: NULL
Timeout: 86400
1 row in set (0.00 sec)
-- JobId:每個(gè) Schema Change 作業(yè)的唯一 ID。
-- TableName:Schema Change 對(duì)應(yīng)的基表的表名。
-- CreateTime:作業(yè)創(chuàng)建時(shí)間。
-- FinishedTime:作業(yè)結(jié)束時(shí)間。如未結(jié)束,則顯示 "N/A"。
-- IndexName: 本次修改所涉及的某一個(gè) Index 的名稱(chēng)。
-- IndexId:新的 Index 的唯一 ID。
-- OriginIndexId:舊的 Index 的唯一 ID。
-- SchemaVersion:以 M:N 的格式展示。其中 M 表示本次 Schema Change 變更的版本,N 表示對(duì)應(yīng)的 Hash 值。每次 Schema Change,版本都會(huì)遞增。
-- TransactionId:轉(zhuǎn)換歷史數(shù)據(jù)的分水嶺 transaction ID。
-- State:作業(yè)所在階段。
-- PENDING:作業(yè)在隊(duì)列中等待被調(diào)度。
-- WAITING_TXN:等待分水嶺 transaction ID 之前的導(dǎo)入任務(wù)完成。
-- RUNNING:歷史數(shù)據(jù)轉(zhuǎn)換中。
-- FINISHED:作業(yè)成功。
-- CANCELLED:作業(yè)失敗。
-- Msg:如果作業(yè)失敗,這里會(huì)顯示失敗信息。
-- Progress:作業(yè)進(jìn)度。只有在 RUNNING 狀態(tài)才會(huì)顯示進(jìn)度。進(jìn)度是以 M/N 的形式顯示。其中 N 為 Schema Change 涉及的總副本數(shù)。M 為已完成歷史數(shù)據(jù)轉(zhuǎn)換的副本數(shù)。
-- Timeout:作業(yè)超時(shí)時(shí)間。單位秒。
取消作業(yè)
在作業(yè)狀態(tài)不為 FINISHED 或 CANCELLED 的情況下,可以通過(guò)以下命令取消Schema Change作業(yè):
CANCEL ALTER TABLE COLUMN FROM tbl_name;
注意事項(xiàng)
? 一張表在同一時(shí)間只能有一個(gè) Schema Change 作業(yè)在運(yùn)行。
? Schema Change 操作不阻塞導(dǎo)入和查詢(xún)操作。
? 分區(qū)列和分桶列不能修改。
? 如果 Schema 中有 REPLACE 方式聚合的 value 列,則不允許刪除 Key 列。
? 如果刪除 Key 列,Doris 無(wú)法決定 REPLACE 列的取值。
? Unique 數(shù)據(jù)模型表的所有非 Key 列都是 REPLACE 聚合方式。
? 在新增聚合類(lèi)型為 SUM 或者 REPLACE 的 value 列時(shí),該列的默認(rèn)值對(duì)歷史數(shù)據(jù)沒(méi)有含義。
? 因?yàn)闅v史數(shù)據(jù)已經(jīng)失去明細(xì)信息,所以默認(rèn)值的取值并不能實(shí)際反映聚合后的取值。
? 當(dāng)修改列類(lèi)型時(shí),除 Type 以外的字段都需要按原列上的信息補(bǔ)全。
? 如修改列 k1 INT SUM NULL DEFAULT "1" 類(lèi)型為 BIGINT,則需執(zhí)行命令如下:
? ALTER TABLE tbl1 MODIFY COLUMN k1 BIGINT SUM NULL DEFAULT "1";
? 注意,除新的列類(lèi)型外,如聚合方式,Nullable 屬性,以及默認(rèn)值都要按照原信息補(bǔ)全。
? 不支持修改列名稱(chēng)、聚合類(lèi)型、Nullable 屬性、默認(rèn)值以及列注釋。
partition的增減
-- 1.增加分區(qū), 使用默認(rèn)分桶方式:現(xiàn)有分區(qū) \[MIN, 2013-01-01),增加分區(qū) \[2013-01-01, 2014-01-01)
ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES LESS THAN ("2014-01-01");
-- 2.增加分區(qū),使用新的分桶數(shù)
ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES LESS THAN ("2015-01-01")
DISTRIBUTED BY HASH(k1) BUCKETS 20;
-- 3.增加分區(qū),使用新的副本數(shù)
ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES LESS THAN ("2015-01-01")
("replication_num"="1");
-- 4.修改分區(qū)副本數(shù)
ALTER TABLE example_db.my_table MODIFY PARTITION p1 SET("replication_num"="1");
-- 5.批量修改指定分區(qū)
ALTER TABLE example_db.my_table MODIFY PARTITION (p1, p2, p4) SET("in_memory"="true");
-- 6.批量修改所有分區(qū)
ALTER TABLE example_db.my_table MODIFY PARTITION (*) SET("storage_medium"="HDD");
-- 7.刪除分區(qū)
ALTER TABLE example_db.my_table DROP PARTITION p1;
-- 8.增加一個(gè)指定上下界的分區(qū)
ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES [("2014-01-01"), ("2014-02-01"));
rollup的增減
-- 1.創(chuàng)建 index: example_rollup_index,基于 base index(k1,k2,k3,v1,v2)。列式存儲(chǔ)。
ALTER TABLE example_db.my_table ADD ROLLUP example_rollup_index(k1, k3, v1, v2);
-- 2.創(chuàng)建 index: example_rollup_index2,基于 example_rollup_index(k1,k3,v1,v2)
ALTER TABLE example_db.my_table ADD ROLLUP example_rollup_index2 (k1, v1)
FROM example_rollup_index;
-- 3.創(chuàng)建 index: example_rollup_index3, 基于base index (k1,k2,k3,v1), 自定義rollup超時(shí)時(shí)間一小時(shí)
ALTER TABLE example_db.my_table ADD ROLLUP example_rollup_index(k1, k3, v1)
PROPERTIES("timeout" = "3600");
-- 4.刪除 index: example_rollup_index2
ALTER TABLE example_db.my_table DROP ROLLUP example_rollup_index2;
動(dòng)態(tài)分區(qū)和臨時(shí)分區(qū)
動(dòng)態(tài)分區(qū)
原理
在某些使用場(chǎng)景下,用戶(hù)會(huì)將表按照天進(jìn)行分區(qū)劃分,每天定時(shí)執(zhí)行例行任務(wù),這時(shí)需要使用方手動(dòng)管理分區(qū),否則可能由于使用方?jīng)]有創(chuàng)建分區(qū)導(dǎo)致數(shù)據(jù)導(dǎo)入失敗,這給使用方帶來(lái)了額外的維護(hù)成本。通過(guò)動(dòng)態(tài)分區(qū)功能,用戶(hù)可以在建表時(shí)設(shè)定動(dòng)態(tài)分區(qū)的規(guī)則。FE 會(huì)啟動(dòng)一個(gè)后臺(tái)線程,根據(jù)用戶(hù)指定的規(guī)則創(chuàng)建或刪除分區(qū)。用戶(hù)也可以在運(yùn)行時(shí)對(duì)現(xiàn)有規(guī)則進(jìn)行變更。
使用方式
動(dòng)態(tài)分區(qū)的規(guī)則可以在建表時(shí)指定,或者在運(yùn)行時(shí)進(jìn)行修改。當(dāng)前僅支持對(duì)單分區(qū)列的分區(qū)表設(shè)定動(dòng)態(tài)分區(qū)規(guī)則
-- 建表時(shí)指定
CREATE TABLE tbl1
(...)
PROPERTIES
(
-- 添加動(dòng)態(tài)分區(qū)的規(guī)則
"dynamic_partition.prop1" = "value1",
"dynamic_partition.prop2" = "value2",
...
)
-- 運(yùn)行時(shí)修改
ALTER TABLE tbl1 SET
(
"dynamic_partition.prop1" = "value1",
"dynamic_partition.prop2" = "value2",
...
)
動(dòng)態(tài)分區(qū)規(guī)則參數(shù)
- dynamic_partition.enable:是否開(kāi)啟動(dòng)態(tài)分區(qū)特性。默認(rèn)是true
- dynamic_partition.time_unit:動(dòng)態(tài)分區(qū)調(diào)度的單位。可指定為 HOUR、DAY、WEEK、MONTH。分別表示按小時(shí)、按天、按星期、按月進(jìn)行分區(qū)創(chuàng)建或刪除。
- dynamic_partition.time_zone:動(dòng)態(tài)分區(qū)的時(shí)區(qū),如果不填寫(xiě),則默認(rèn)為當(dāng)前機(jī)器的系統(tǒng)的時(shí)區(qū)
- dynamic_partition.start:動(dòng)態(tài)分區(qū)的起始偏移,為負(fù)數(shù)。以當(dāng)天(星期/月)為基準(zhǔn),分區(qū)范圍在此偏移之前的分區(qū)將會(huì)被刪除。如果不填寫(xiě),則默認(rèn)為 -2147483648,即不刪除歷史分區(qū)。
- dynamic_partition.end:動(dòng)態(tài)分區(qū)的結(jié)束偏移,為正數(shù)。根據(jù) time_unit 屬性的不同,以當(dāng)天(星期/月)為基準(zhǔn),提前創(chuàng)建對(duì)應(yīng)范圍的分區(qū)。
- dynamic_partition.prefix:動(dòng)態(tài)創(chuàng)建的分區(qū)名前綴。
- dynamic_partition.buckets:動(dòng)態(tài)創(chuàng)建的分區(qū)所對(duì)應(yīng)的分桶數(shù)量
- dynamic_partition.replication_num:動(dòng)態(tài)創(chuàng)建的分區(qū)所對(duì)應(yīng)的副本數(shù)量,如果不填寫(xiě),則默認(rèn)為該表創(chuàng)建時(shí)指定的副本數(shù)量
- dynamic_partition.start_day_of_week:當(dāng) time_unit 為 WEEK 時(shí),該參數(shù)用于指定每周的起始點(diǎn)。取值為 1 到 7。其中 1 表示周一,7 表示周日。默認(rèn)為 1,即表示每周以周一為起始點(diǎn)。
- dynamic_partition.start_day_of_month:當(dāng) time_unit 為 MONTH 時(shí),該參數(shù)用于指定每月的起始日期。取值為 1 到 28。其中 1 表示每月1號(hào),28 表示每月28號(hào)。默認(rèn)為 1,即表示每月以1號(hào)位起始點(diǎn)。暫不支持以29、30、31號(hào)為起始日,以避免因閏年或閏月帶來(lái)的歧義
- dynamic_partition.create_history_partition:為 true 時(shí)代表可以創(chuàng)建歷史分區(qū),默認(rèn)是false
- dynamic_partition.history_partition_num:當(dāng) create_history_partition 為 true 時(shí),該參數(shù)用于指定創(chuàng)建歷史分區(qū)數(shù)量。默認(rèn)值為 -1, 即未設(shè)置。
- dynamic_partition.hot_partition_num:指定最新的多少個(gè)分區(qū)為熱分區(qū)。對(duì)于熱分區(qū),系統(tǒng)會(huì)自動(dòng)設(shè)置其 storage_medium 參數(shù)為SSD,并且設(shè)置 storage_cooldown_time 。hot_partition_num:設(shè)置往前 n 天和未來(lái)所有分區(qū)為熱分區(qū),并自動(dòng)設(shè)置冷卻時(shí)間
- dynamic_partition.reserved_history_periods:需要保留的歷史分區(qū)的時(shí)間范圍。
修改動(dòng)態(tài)分區(qū)屬性
ALTER TABLE tbl1 SET
(
"dynamic_partition.prop1" = "value1",
...
);
ALTER TABLE partition_test SET
(
"dynamic_partition.time_unit" = "week",
"dynamic_partition.start" = "-1",
"dynamic_partition.end" = "1"
);
某些屬性的修改可能會(huì)產(chǎn)生沖突。假設(shè)之前分區(qū)粒度為 DAY,并且已經(jīng)創(chuàng)建了如下分區(qū):
p20200519: ["2020-05-19", "2020-05-20")
p20200520: ["2020-05-20", "2020-05-21")
p20200521: ["2020-05-21", "2020-05-22")
如果此時(shí)將分區(qū)粒度改為 MONTH,則系統(tǒng)會(huì)嘗試創(chuàng)建范圍為 ["2020-05-01", "2020-06-01") 的分區(qū),而該分區(qū)的分區(qū)范圍和已有分區(qū)沖突,所以無(wú)法創(chuàng)建。而范圍為 ["2020-06-01", "2020-07-01") 的分區(qū)可以正常創(chuàng)建。因此,2020-05-22 到 2020-05-30 時(shí)間段的分區(qū),需要自行填補(bǔ)。
查看動(dòng)態(tài)分區(qū)表調(diào)度情況
-- 通過(guò)以下命令可以進(jìn)一步查看當(dāng)前數(shù)據(jù)庫(kù)下,所有動(dòng)態(tài)分區(qū)表的調(diào)度情況:
SHOW DYNAMIC PARTITION TABLES;
-- LastUpdateTime: 最后一次修改動(dòng)態(tài)分區(qū)屬性的時(shí)間
-- LastSchedulerTime: 最后一次執(zhí)行動(dòng)態(tài)分區(qū)調(diào)度的時(shí)間
-- State: 最后一次執(zhí)行動(dòng)態(tài)分區(qū)調(diào)度的狀態(tài)
-- LastCreatePartitionMsg: 最后一次執(zhí)行動(dòng)態(tài)添加分區(qū)調(diào)度的錯(cuò)誤信息
-- LastDropPartitionMsg: 最后一次執(zhí)行動(dòng)態(tài)刪除分區(qū)調(diào)度的錯(cuò)誤信息
臨時(shí)分區(qū)
規(guī)則
? 臨時(shí)分區(qū)的分區(qū)列和正式分區(qū)相同,且不可修改。
? 一張表所有臨時(shí)分區(qū)之間的分區(qū)范圍不可重疊,但臨時(shí)分區(qū)的范圍和正式分區(qū)范圍可以重疊。
? 臨時(shí)分區(qū)的分區(qū)名稱(chēng)不能和正式分區(qū)以及其他臨時(shí)分區(qū)重復(fù)。
操作
臨時(shí)分區(qū)支持添加、刪除、替換操作。
添加臨時(shí)分區(qū)
可以通過(guò) ALTER TABLE ADD TEMPORARY PARTITION 語(yǔ)句對(duì)一個(gè)表添加臨時(shí)分區(qū):
ALTER TABLE tbl1 ADD TEMPORARY PARTITION tp1 VALUES LESS THAN("2020-02-01");
ALTER TABLE tbl1 ADD TEMPORARY PARTITION tp2 VALUES LESS THAN("2020-02-02")
("in_memory" = "true", "replication_num" = "1")
DISTRIBUTED BY HASH(k1) BUCKETS 5;
ALTER TABLE tbl3 ADD TEMPORARY PARTITION tp1 VALUES IN ("Beijing", "Shanghai");
ALTER TABLE tbl3 ADD TEMPORARY PARTITION tp1 VALUES IN ("Beijing", "Shanghai")
("in_memory" = "true", "replication_num" = "1")
DISTRIBUTED BY HASH(k1) BUCKETS 5;
-- 添加操作的一些說(shuō)明:
-- 臨時(shí)分區(qū)的添加和正式分區(qū)的添加操作相似。臨時(shí)分區(qū)的分區(qū)范圍獨(dú)立于正式分區(qū)。
-- 臨時(shí)分區(qū)可以獨(dú)立指定一些屬性。包括分桶數(shù)、副本數(shù)、是否是內(nèi)存表、存儲(chǔ)介質(zhì)等信息。
刪除臨時(shí)分區(qū)
-- 可以通過(guò) ALTER TABLE DROP TEMPORARY PARTITION 語(yǔ)句刪除一個(gè)表的臨時(shí)分區(qū):
ALTER TABLE tbl1 DROP TEMPORARY PARTITION tp1;
-- 刪除臨時(shí)分區(qū),不影響正式分區(qū)的數(shù)據(jù)。
替換分區(qū)
可以通過(guò) ALTER TABLE REPLACE PARTITION 語(yǔ)句將一個(gè)表的正式分區(qū)替換為臨時(shí)分區(qū)。
-- 正式分區(qū)替換成臨時(shí)分區(qū)以后,正是分區(qū)的數(shù)據(jù)會(huì)被刪除,并且這個(gè)過(guò)程是不可逆的
-- 用之前要小心
ALTER TABLE tbl1 REPLACE PARTITION (p1) WITH TEMPORARY PARTITION (tp1);
ALTER TABLE partition_test REPLACE PARTITION (p20230104) WITH TEMPORARY PARTITION (tp1);
ALTER TABLE tbl1 REPLACE PARTITION (p1, p2) WITH TEMPORARY PARTITION (tp1, tp2)
PROPERTIES (
"strict_range" = "false",
"use_temp_partition_name" = "true"
);
-- strict_range:默認(rèn)為 true。
-- 對(duì)于 Range 分區(qū),當(dāng)該參數(shù)為 true 時(shí),表示要被替換的所有正式分區(qū)的范圍并集需要和替換的臨時(shí)分區(qū)的范圍并集完全相同。當(dāng)置為 false 時(shí),只需要保證替換后,新的正式分區(qū)間的范圍不重疊即可。
-- 對(duì)于 List 分區(qū),該參數(shù)恒為 true。要被替換的所有正式分區(qū)的枚舉值必須和替換的臨時(shí)分區(qū)枚舉值完全相同。
-- use_temp_partition_name:默認(rèn)為 false。當(dāng)該參數(shù)為 false,并且待替換的分區(qū)和替換分區(qū)的個(gè)數(shù)相同時(shí),則替換后的正式分區(qū)名稱(chēng)維持不變。如果為 true,則替換后,正式分區(qū)的名稱(chēng)為替換分區(qū)的名稱(chēng)。
LTER TABLE tbl1 REPLACE PARTITION (p1) WITH TEMPORARY PARTITION (tp1);
-- use_temp_partition_name 默認(rèn)為 false,則在替換后,分區(qū)的名稱(chēng)依然為 p1,但是相關(guān)的數(shù)據(jù)和屬性都替換為 tp1 的。 如果 use_temp_partition_name 默認(rèn)為 true,則在替換后,分區(qū)的名稱(chēng)為 tp1。p1 分區(qū)不再存在。
ALTER TABLE tbl1 REPLACE PARTITION (p1, p2) WITH TEMPORARY PARTITION (tp1);
-- use_temp_partition_name 默認(rèn)為 false,但因?yàn)榇鎿Q分區(qū)的個(gè)數(shù)和替換分區(qū)的個(gè)數(shù)不同,則該參數(shù)無(wú)效。替換后,分區(qū)名稱(chēng)為 tp1,p1 和 p2 不再存在。
-- 替換操作的一些說(shuō)明:
-- 分區(qū)替換成功后,被替換的分區(qū)將被刪除且不可恢復(fù)。
數(shù)據(jù)的導(dǎo)入和查詢(xún)
導(dǎo)入臨時(shí)分區(qū)
根據(jù)導(dǎo)入方式的不同,指定導(dǎo)入臨時(shí)分區(qū)的語(yǔ)法稍有差別。這里通過(guò)示例進(jìn)行簡(jiǎn)單說(shuō)明
-- 查詢(xún)結(jié)果用insert導(dǎo)入
INSERT INTO tbl TEMPORARY PARTITION(tp1, tp2, ...) SELECT ....
-- 查看數(shù)據(jù)
SELECT ... FROM
tbl1 TEMPORARY PARTITION(tp1, tp2, ...)
JOIN
tbl2 TEMPORARY PARTITION(tp1, tp2, ...)
ON ...
WHERE ...;
doris中join的優(yōu)化原理
Shuffle Join(Partitioned Join)
和mr中的shuffle過(guò)程是一樣的,針對(duì)每個(gè)節(jié)點(diǎn)上的數(shù)據(jù)進(jìn)行shuffle,相同數(shù)據(jù)分發(fā)到下游的節(jié)點(diǎn)上的join方式叫shuffle join
-- 訂單表
CREATE TABLE test.order_info_shuffle
(
`order_id` varchar(20) COMMENT "訂單id",
`user_id` varchar(20) COMMENT "用戶(hù)id",
`goods_id` VARCHAR(20) COMMENT "商品id",
`goods_num` Int COMMENT "商品數(shù)量",
`price` double COMMENT "商品價(jià)格"
)
duplicate KEY(`order_id`)
DISTRIBUTED BY HASH(`order_id`) BUCKETS 5;
-- 導(dǎo)入數(shù)據(jù):
insert into test.order_info_shuffle values\
('o001','u001','g001',1,9.9 ),\
('o001','u001','g002',2,19.9),\
('o001','u001','g003',2,39.9),\
('o002','u002','g001',3,9.9 ),\
('o002','u002','g002',1,19.9),\
('o003','u002','g003',1,39.9),\
('o003','u002','g002',2,19.9),\
('o003','u002','g004',3,99.9),\
('o003','u002','g005',1,99.9),\
('o004','u003','g001',2,9.9 ),\
('o004','u003','g002',1,19.9),\
('o004','u003','g003',4,39.9),\
('o004','u003','g004',1,99.9),\
('o004','u003','g005',4,89.9);
-- 商品表
CREATE TABLE test.goods_shuffle
(
`goods_id` VARCHAR(20) COMMENT "商品id",
`goods_name` VARCHAR(20) COMMENT "商品名稱(chēng)",
`category_id` VARCHAR(20) COMMENT "商品品類(lèi)id"
)
duplicate KEY(`goods_id`)
DISTRIBUTED BY HASH(`goods_id`) BUCKETS 5;
-- 導(dǎo)入數(shù)據(jù):
insert into test.goods_shuffle values\
('g001','iphon13','c001'),\
('g002','ipad','c002'),\
('g003','xiaomi12','c001'),\
('g004','huaweip40','c001'),\
('g005','headset','c003');
-- sql示例
EXPLAIN
select
oi.order_id,
oi.user_id,
oi.goods_id,
gs.goods_name,
gs.category_id,
oi.goods_num,
oi.price
from order_info_shuffle as oi
-- 我們可以不指定哪一種join方式,doris會(huì)自己根據(jù)數(shù)據(jù)的實(shí)際情況幫我們選擇
JOIN goods_shuffle as gs
on oi.goods_id = gs.goods_id;
EXPLAIN select
oi.order_id,
oi.user_id,
oi.goods_id,
gs.goods_name,
gs.category_id,
oi.goods_num,
oi.price
from order_info_shuffle as oi
-- 可以顯式的hint指定我們想要的join類(lèi)型
JOIN [broadcast] goods_shuffle as gs
on oi.goods_id = gs.goods_id;
適用場(chǎng)景:不管數(shù)據(jù)量,不管是大表join大表還是大表join小表都可以用
優(yōu)點(diǎn):通用
缺點(diǎn):需要shuffle內(nèi)存和網(wǎng)絡(luò)開(kāi)銷(xiāo)比較大,效率不高
Broadcast Join
當(dāng)一個(gè)大表join小表的時(shí)候,將小表廣播到每一個(gè)大表所在的每一個(gè)節(jié)點(diǎn)上(以hash表的形式放在內(nèi)存中)這樣的方式叫做Broadcast Join,類(lèi)似于mr里面的一個(gè)map端join
-- 顯式使用 Broadcast Join:
EXPLAIN
select
oi.order_id,
oi.user_id,
oi.goods_id,
gs.goods_name,
gs.category_id,
oi.goods_num,
oi.price
from order_info_broadcast as oi
JOIN [broadcast] goods_broadcast as gs
on oi.goods_id = gs.goods_id;
適用場(chǎng)景:
左表join右表,要求左表的數(shù)據(jù)量相對(duì)來(lái)說(shuō)比較大,右表數(shù)據(jù)量比較小
優(yōu)點(diǎn):避免了shuffle,提高了運(yùn)算效率
缺點(diǎn):有限制,必須右表數(shù)據(jù)量比較小
Bucket Shuffle Join
利用建表時(shí)候分桶的特性,當(dāng)join的時(shí)候,join的條件和左表的分桶字段一樣的時(shí)候,將右表按照左表分桶的規(guī)則進(jìn)行shuffle操作,使右表中需要join的數(shù)據(jù)落在左表中需要join數(shù)據(jù)的BE節(jié)點(diǎn)上的join方式叫做Bucket Shuffle Join。
-- 從 0.14 版本開(kāi)始默認(rèn)為 true,新版本可以不用設(shè)置這個(gè)參數(shù)了!
show variables like '%bucket_shuffle_join%';
set enable_bucket_shuffle_join = true;
-- 通過(guò) explain 查看 join 類(lèi)型
EXPLAIN
select
oi.order_id,
oi.user_id,
oi.goods_id,
gs.goods_name,
gs.category_id,
oi.goods_num,
oi.price
from order_info_bucket as oi
-- 目前 Bucket Shuffle Join不能像Shuffle Join那樣可以顯示指定Join方式,
-- 只能讓執(zhí)行引擎自動(dòng)選擇,
-- 選擇的順序:Colocate Join -> Bucket Shuffle Join -> Broadcast Join -> Shuffle Join。
JOIN goods_bucket as gs
where oi.goods_id = gs.goods_id;
EXPLAIN select
oi.order_id,
oi.user_id,
oi.goods_id,
gs.goods_name,
gs.category_id,
oi.goods_num,
oi.price
from order_info_bucket as oi
-- 目前 Bucket Shuffle Join不能像Shuffle Join那樣可以顯示指定Join方式,
-- 只能讓執(zhí)行引擎自動(dòng)選擇,
-- 選擇的順序:Colocate Join -> Bucket Shuffle Join -> Broadcast Join -> Shuffle Join。
JOIN goods_bucket1 as gs
where oi.goods_id = gs.goods_id;
-- 注意事項(xiàng):
-- Bucket Shuffle Join 只生效于 Join 條件為等值的場(chǎng)景
-- Bucket Shuffle Join 要求左表的分桶列的類(lèi)型與右表等值 join 列的類(lèi)型需要保持一致,否則無(wú)法進(jìn)行對(duì)應(yīng)的規(guī)劃。
-- Bucket Shuffle Join 只作用于 Doris 原生的 OLAP 表,對(duì)于 ODBC,MySQL,ES 等外表,當(dāng)其作為左表時(shí)是無(wú)法規(guī)劃生效的。
-- Bucket Shuffle Join只能保證左表為單分區(qū)時(shí)生效。所以在 SQL 執(zhí)行之中,需要盡量使用 where 條件使分區(qū)裁剪的策略能夠生效。
Colocation Join
中文意思叫位置協(xié)同分組join,指需要join的兩份數(shù)據(jù)都在同一個(gè)BE節(jié)點(diǎn)上,這樣在join的時(shí)候,直接本地join計(jì)算即可,不需要進(jìn)行shuffle。
名詞解釋
? Colocation Group(位置協(xié)同組CG):在同一個(gè) CG內(nèi)的 Table 有著相同的 Colocation Group Schema,并且有著相同的數(shù)據(jù)分片分布(滿(mǎn)足三個(gè)條件)。
? Colocation Group Schema(CGS):用于描述一個(gè) CG 中的 Table,和 Colocation 相關(guān)的通用 Schema 信息。包括分桶列類(lèi)型,分桶數(shù)以及分區(qū)的副本數(shù)等。
使用限制
- 建表時(shí)兩張表的分桶列的類(lèi)型和數(shù)量需要完全一致,并且桶數(shù)一致,才能保證多張表的數(shù)據(jù)分片能夠一一對(duì)應(yīng)的進(jìn)行分布控制。
- 同一個(gè) CG 內(nèi)所有表的所有分區(qū)(Partition)的副本數(shù)必須一致。如果不一致,可能出現(xiàn)某一個(gè)Tablet 的某一個(gè)副本,在同一個(gè) BE 上沒(méi)有其他的表分片的副本對(duì)應(yīng)
- 同一個(gè) CG 內(nèi)的表,分區(qū)的個(gè)數(shù)、范圍以及分區(qū)列的類(lèi)型不要求一致。
使用案例
-- 建兩張表,分桶列都為 int 類(lèi)型,且桶的個(gè)數(shù)都是 5 個(gè)。副本數(shù)都為默認(rèn)副本數(shù)
-- 編寫(xiě)查詢(xún)語(yǔ)句,并查看執(zhí)行計(jì)劃
EXPLAIN
select
oi.order_id,
oi.user_id,
oi.goods_id,
gs.goods_name,
gs.category_id,
oi.goods_num,
oi.price
from order_info_colocation as oi
-- 目前 Colocation Join不能像Shuffle Join那樣可以顯示指定Join方式,
-- 只能讓執(zhí)行引擎自動(dòng)選擇,
-- 選擇的順序:Colocate Join -> Bucket Shuffle Join -> Broadcast Join -> Shuffle Join。
JOIN goods_colocation as gs
where oi.goods_id = gs.goods_id;
-- 查看 Group
SHOW PROC '/colocation_group';
-- 當(dāng) Group 中最后一張表徹底刪除后(徹底刪除是指從回收站中刪除。通常,一張表通過(guò)DROP TABLE 命令刪除后,會(huì)在回收站默認(rèn)停留一天的時(shí)間后,再刪除),該 Group 也會(huì)被自動(dòng)刪除。
-- 修改表 Colocate Group 屬性
ALTER TABLE tbl SET ("colocate_with" = "group2");
-- 如果被修改的表原來(lái)有g(shù)roup,那么會(huì)直接將原來(lái)的group刪除后創(chuàng)建新的group, 如果原來(lái)沒(méi)有組,就直接創(chuàng)建
-- 刪除表的 Colocation 屬性
ALTER TABLE tbl SET ("colocate_with" = "");
-- 當(dāng)對(duì)一個(gè)具有 Colocation 屬性的表進(jìn)行增加分區(qū)(ADD PARTITION)、修改副本數(shù)時(shí),Doris 會(huì)檢查修改是否會(huì)違反 Colocation Group Schema,如果違反則會(huì)拒絕
Runtime Filter
Runtime Filter會(huì)在有join動(dòng)作的 sql運(yùn)行時(shí),創(chuàng)建一個(gè)HashJoinNode和一個(gè)ScanNode來(lái)對(duì)join的數(shù)據(jù)進(jìn)行過(guò)濾優(yōu)化,使得join的時(shí)候數(shù)據(jù)量變少,從而提高效率
使用
-- 指定 RuntimeFilter 類(lèi)型
set runtime_filter_type="BLOOM_FILTER,IN,MIN_MAX";
set runtime_filter_type="MIN_MAX";
參數(shù)解釋?zhuān)?/strong>文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-467395.html
- runtime_filter_type: 包括Bloom Filter、MinMax Filter、IN predicate、IN Or Bloom Filter
- Bloom Filter: 針對(duì)右表中的join字段的所有數(shù)據(jù)標(biāo)注在一個(gè)布隆過(guò)濾器中,從而判斷左表中需要join的數(shù)據(jù)在還是不在
- MinMax Filter: 獲取到右表表中數(shù)據(jù)的最大值和最小值,看左表中查看,將超出這個(gè)最大值最小值范圍的數(shù)據(jù)過(guò)濾掉
- IN predicate: 將右表中需要join字段所有數(shù)據(jù)構(gòu)建一個(gè)IN predicate,再去左表表中過(guò)濾無(wú)意義數(shù)據(jù)
- runtime_filter_wait_time_ms: 左表的ScanNode等待每個(gè)Runtime Filter的時(shí)間,默認(rèn)1000ms
- runtime_filters_max_num: 每個(gè)查詢(xún)可應(yīng)用的Runtime Filter中Bloom Filter的最大數(shù)量,默認(rèn)10
- runtime_bloom_filter_min_size: Runtime Filter中Bloom Filter的最小長(zhǎng)度,默認(rèn)1M
- runtime_bloom_filter_max_size: Runtime Filter中Bloom Filter的最大長(zhǎng)度,默認(rèn)16M
- runtime_bloom_filter_size: Runtime Filter中Bloom Filter的默認(rèn)長(zhǎng)度,默認(rèn)2M
- runtime_filter_max_in_num: 如果join右表數(shù)據(jù)行數(shù)大于這個(gè)值,我們將不生成IN predicate,默認(rèn)102400
示例文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-467395.html
-- 建表
CREATE TABLE test (t1 INT) DISTRIBUTED BY HASH (t1) BUCKETS 2
PROPERTIES("replication_num" = "1");
INSERT INTO test VALUES (1), (2), (3), (4);
CREATE TABLE test2 (t2 INT) DISTRIBUTED BY HASH (t2) BUCKETS 2
PROPERTIES("replication_num" = "1");
INSERT INTO test2 VALUES (3), (4), (5);
-- 查看執(zhí)行計(jì)劃
set runtime_filter_type="BLOOM_FILTER,IN,MIN_MAX";
EXPLAIN SELECT t1 FROM test JOIN test2 where test.t1 = test2.t2;
到了這里,關(guān)于Doris(七) -- 修改表、動(dòng)態(tài)和臨時(shí)分區(qū)、join的優(yōu)化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!