當單表資料量過大導致查詢緩慢,或初期設定的分區策略不合理引發資料熱點時,原有的表結構可能成為業務瓶頸。為解決此類問題,PolarDB分布式版提供了線上(Online)變更表類型和分區策略的功能。可以在不中斷業務(不鎖表、不阻塞DML)的情況下,對錶進行資料重分布,實現單表、廣播表、分區表之間的相互轉換,或調整現有分區表的分區鍵、分區演算法,以最佳化資料布局,提升資料庫整體效能和可擴充性。
此操作屬於重型DDL任務,其本質是線上進行全量資料移轉和重分布。
執行期間會消耗大量的CPU、IO和網路資源,可能對執行個體效能產生影響,且耗時與資料量成正比。
建議在業務低峰期執行,並配合使用任務管理命令進行監控。
適用範圍
執行變更前,需確保環境滿足以下條件。
資料庫模式:僅適用於AUTO模式資料庫。
執行個體版本:僅支援PolarDB-X 2.0,且核心小版本需為
5.4.13及以上版本。全域二級索引(GSI):僅支援PolarDB-X 2.0,且核心小版本需為
5.4.14及以上版本對帶有GSI的分區表進行分區變更。變更過程中,GSI的資料會同步進行重分布。
工作原理
線上DDL:所有變更操作均以線上方式執行,期間不鎖定原表,DML/SELECT操作均可正常進行,保障商務持續性。
資料重分布:變更表類型或分區策略的核心是資料的物理遷移。例如:
將單錶轉為分區表時,資料會從單個資料節點(DN)分散到多個DN。
變更分區鍵時,資料會根據新的分區策略在DN間重新平衡。此過程是資源消耗的主要原因。
原子性與可復原:整個DDL任務具備原子性。如果任務因唯一鍵衝突、磁碟空間不足等原因執行失敗,系統會確保原表資料完好無損,業務不受影響。失敗的任務可通過 CANCEL DDL命令復原該任務。
變更表類型
PolarDB分布式版支援單表、廣播表和分區表三種類型,可根據業務情境的變化在它們之間進行線上轉換。詳細資料,請參見CREATE TABLE(AUTO模式)。
變更表類型時,如果原表為主鍵分區表(即分區鍵與主鍵一致),在將其變更為普通表後,該表將不再具備主鍵分區表的特性,例如自動分區策略或索引轉換規則。詳細資料,請參見AUTO模式下的主鍵拆分。
將單表或廣播表變更為分區表
此情境適用於單表資料量持續增長,已成為或即將成為效能瓶頸,需要將其水平分割以提升擴充性和查詢效能。
文法說明
使用ALTER TABLE語句並指定新的分區策略。關於partition_options的詳細文法,請參見分區表。
ALTER TABLE table_name PARTITION BY partition_options;樣本
建立一個樣本表
t_order。CREATE TABLE t_order ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext DEFAULT NULL, `order_detail` longtext DEFAULT NULL, PRIMARY KEY (`id`), KEY `l_i_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;因業務發展導致單表
t_order資料量劇增,現決定將其變更為以order_id為分區鍵的分區表。-- 將單表 t_order 變更為以 order_id 為分區鍵的KEY分區表 ALTER TABLE t_order PARTITION BY KEY(`order_id`); -- 也可以在變更的同時指定分區數量 ALTER TABLE t_order PARTITION BY KEY(`order_id`) PARTITIONS 8;
將分區表或單表變更為廣播表
該情境適用於資料量較小且幾乎不增長的表,但這些表頻繁與其他大型表進行關聯查詢(JOIN),例如配置表和字典表。通過將表資料複製到每個資料節點(DN),可以消除跨庫JOIN所帶來的網路開銷,從而提升關聯查詢的效能。
文法說明
使用 ALTER TABLE語句並指定BROADCAST子句。
ALTER TABLE table_name BROADCAST;廣播表的資料會在所有DN節點上存有副本,會佔用更多儲存空間。
樣本
建立一個樣本表
t_order_1。CREATE TABLE t_order_1 ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext DEFAULT NULL, `order_detail` longtext DEFAULT NULL, PRIMARY KEY (`id`), KEY `l_i_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;將
t_order_1表變更為廣播表。ALTER TABLE t_order_1 BROADCAST;
將分區表或廣播表變更為單表
此情境適用於資料量較小且無需進行水平擴充的表。將表的資料集中到單個資料節點(DN)上,以簡化表結構。
文法說明
使用ALTER TABLE語句並指定SINGLE子句。
ALTER TABLE table_name SINGLE;將分區表變更為單表時,所有分區的資料都會匯聚到同一個DN節點。需確保目標節點的磁碟空間充足,避免因空間不足導致操作失敗。
樣本
建立一個樣本表
t_order_2。CREATE TABLE t_order_2 ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, `seller_id` varchar(20) DEFAULT NULL, `order_snapshot` longtext DEFAULT NULL, `order_detail` longtext DEFAULT NULL, PRIMARY KEY (`id`), KEY `l_i_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 PARTITION BY KEY(`order_id`) PARTITIONS 8;將
t_order_2表變更為單表。ALTER TABLE t_order_2 SINGLE;
變更分區表的分區策略
當現有的分區策略無法滿足業務需求時,例如由於分區鍵選擇不當導致的資料扭曲,或業務查詢模式的變化,可以線上調整分區策略。通過對分區鍵、分區函數或分區數量進行修改,重新最佳化資料的物理分布,以解決資料熱點問題,適應新的業務模型。
文法說明
使用ALTER TABLE語句並指定新的分區策略。
ALTER TABLE tbl_name PARTITION BY new_partition_options;如果原表是主鍵分區表(即分區鍵與主鍵一致),在變更分區策略後,若新的分區鍵不再是主鍵,該表將不再具備主鍵分區表的特性(如自動建立分區等)。詳細資料,請參見AUTO模式下的主鍵拆分。
在變更分區策略後,如果主鍵列未包含全部分區列,則該主鍵為Local主鍵,只能保證分區內唯一,無法保證全域唯一。詳細資料,請參見主鍵與唯一鍵(AUTO模式)。
樣本
變更分區鍵
建立一個t_order_3表當前按order_id分區,但多數查詢基於buyer_id,導致跨分區查詢較多。現需要將分區鍵變更為buyer_id,並將分區數設定為16。
原表結構。
CREATE TABLE t_order_3 ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 PARTITION BY KEY(`order_id`) PARTITIONS 8;執行變更。
ALTER TABLE t_order_3 PARTITION BY KEY(buyer_id) PARTITIONS 16;變更後表結構:系統會自動建立新的分區鍵索引
auto_shard_key_buyer_id。SHOW FULL CREATE TABLE t_order_3;+-----------+-----------------------------------------------------------------------+ | Table | Create Table | +-----------+-----------------------------------------------------------------------+ | t_order_3 | CREATE TABLE `t_order_3` ( `id` bigint NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`), LOCAL KEY `auto_shard_key_buyer_id` USING BTREE (`buyer_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 DEFAULT COLLATE = utf8mb4_0900_ai_ci PARTITION BY KEY(`buyer_id`) PARTITIONS 16 /* tablegroup = `tg12` */ | +-----------+---------------------------------------------------------------------+
變更分區策略
建立一個t_order_4表目前根據id進行RANGE分區,但大多數查詢是基於order_id和buyer_id。因此,需要將其變更為以order_id和buyer_id作為分區鍵的KEY分區,並將分區數設定為16。
原表結構。
CREATE TABLE t_order_4 ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 PARTITION BY RANGE(`id`) ( PARTITION p1 VALUES LESS THAN (100), PARTITION p2 VALUES LESS THAN (1000), PARTITION P3 VALUES LESS THAN MAXVALUE );執行變更。
ALTER TABLE t_order_4 PARTITION BY KEY(order_id, buyer_id) PARTITIONS 16;變更後表結構:系統會自動建立新的分區鍵索引
auto_shard_key_order_id_buyer_id。SHOW FULL CREATE TABLE t_order_4;+-----------+--------------------------------------------------------------------------------+ | Table | Create Table | +-----------+--------------------------------------------------------------------------------+ | t_order_4 | CREATE TABLE `t_order_4` ( `id` bigint NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`), LOCAL KEY `auto_shard_key_order_id_buyer_id` USING BTREE (`order_id`, `buyer_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3 PARTITION BY KEY(`order_id`,`buyer_id`) PARTITIONS 16 /* tablegroup = `tg15` */ | +-----------+------------------------------------------------------------------------------+
增加分區數量
隨著資料量增長,需要增加分區數以分散資料。
原表結構。
CREATE TABLE t_order_5 ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 PARTITION BY KEY(`order_id`) PARTITIONS 8;執行變更。
ALTER TABLE t_order_5 PARTITION BY KEY(order_id) PARTITIONS 128;變更後,分區數將從8個擴充到128個。
SHOW FULL CREATE TABLE t_order_5;+-----------+----------------------------------------------------------+ | Table | Create Table | +-----------+----------------------------------------------------------+ | t_order_4 | CREATE TABLE `t_order_5` ( `id` bigint NOT NULL AUTO_INCREMENT, `order_id` varchar(20) DEFAULT NULL, `buyer_id` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`), LOCAL KEY `auto_shard_key_order_id` USING BTREE (`order_id`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3 PARTITION BY KEY(`order_id`) PARTITIONS 128 /* tablegroup = `tg13` */ | +-----------+---------------------------------------------------------+
任務管理與應急處理
對於耗時較長的資料重分布DDL任務,可使用以下命令進行全生命週期管理。
監控任務進度:使用SHOW DDL命令可以查看當前正在執行或歷史的DDL工作清單及其狀態。
暫停與恢複任務:如果DDL任務對業務高峰期的效能產生較大影響,可以先暫停,待低峰期再恢複。
-- 暫停任務,從 SHOW DDL 的結果中擷取 JobId PAUSE DDL <JobId>; -- 恢複任務 CONTINUE DDL <JobId>;終止與復原任務:如果DDL任務執行失敗,或希望主動取消正在執行的任務,可使用CANCEL DDL命令。該操作會復原所有變更,使表結構和資料恢複到任務開始前的狀態。
-- 復原任務,從 SHOW DDL 的結果中擷取 JobId CANCEL DDL <JobId>;
應用於生產環境
執行時機:建議在業務低峰期執行此類操作,以減少對線上業務的潛在效能影響。
容量規劃:執行變更前,需評定目標資料節點(DN)的磁碟空間、CPU和IOPS資源是否充足,特別是對於分區錶轉單表或資料重分布劇烈的情境,避免因資源不足導致任務失敗。
操作前備份:儘管DDL任務失敗可復原,但在生產環境執行任何重大變更前,建議完成一次全量資料備份。
驗證:任務完成後,可使用
SHOW CREATE TABLE <tablename>查看新的表定義,或使用SHOW TOPOLOGY查看新的資料分區拓撲。