全部產品
Search
文件中心

:變更表類型及分區策略(AUTO模式)

更新時間:Nov 20, 2025

當單表資料量過大導致查詢緩慢,或初期設定的分區策略不合理引發資料熱點時,原有的表結構可能成為業務瓶頸。為解決此類問題,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;

樣本

  1. 建立一個樣本表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;
  2. 因業務發展導致單表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節點上存有副本,會佔用更多儲存空間。

樣本

  1. 建立一個樣本表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;
  2. t_order_1表變更為廣播表。

    ALTER TABLE t_order_1 BROADCAST;

將分區表或廣播表變更為單表

此情境適用於資料量較小且無需進行水平擴充的表。將表的資料集中到單個資料節點(DN)上,以簡化表結構。

文法說明

使用ALTER TABLE語句並指定SINGLE子句。

ALTER TABLE table_name SINGLE;
說明

將分區表變更為單表時,所有分區的資料都會匯聚到同一個DN節點。需確保目標節點的磁碟空間充足,避免因空間不足導致操作失敗。

樣本

  1. 建立一個樣本表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;
  2. 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。

  1. 原表結構。

    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;
  2. 執行變更。

    ALTER TABLE t_order_3 PARTITION BY KEY(buyer_id) PARTITIONS 16;
  3. 變更後表結構:系統會自動建立新的分區鍵索引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_idbuyer_id。因此,需要將其變更為以order_idbuyer_id作為分區鍵的KEY分區,並將分區數設定為16。

  1. 原表結構。

    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
    );
  2. 執行變更。

    ALTER TABLE t_order_4 PARTITION BY KEY(order_id, buyer_id) PARTITIONS 16;
  3. 變更後表結構:系統會自動建立新的分區鍵索引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` */ |
    +-----------+------------------------------------------------------------------------------+

增加分區數量

隨著資料量增長,需要增加分區數以分散資料。

  1. 原表結構。

    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;
  2. 執行變更。

    ALTER TABLE t_order_5 PARTITION BY KEY(order_id) PARTITIONS 128;
  3. 變更後,分區數將從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查看新的資料分區拓撲。

常見問題

為什麼分區鍵變更的DDL任務會執行失敗?如何處理?

常見失敗原因包括執行個體崩潰、目標節點磁碟空間不足、或資料移轉過程中出現唯一索引衝突。任務失敗不會損壞原表資料,也不會阻塞正常的DML和查詢。可通過SHOW DDL查看失敗原因,處理完問題後(如清理磁碟、處理衝突資料),使用CANCEL DDL命令復原失敗的任務,然後重新嘗試執行。

變更分區策略這類操作耗時都很長嗎?新增一個空分區這樣的操作也慢嗎?

並非所有分區操作都是重型操作。變更表類型和變更分區策略因為涉及全量資料移轉,所以耗時較長。而為RANGE/LIST分區表增加一個未來的空分區(例如ALTER TABLE ... ADD PARTITION),通常是秒級的中繼資料操作,對業務影響極小。

如果新分區鍵上已經有一個索引,系統還會自動建立 auto_shard_key_... 索引嗎?

系統會檢查新分區鍵列是否是某個現有索引的最左首碼。如果是,則會複用該索引進行分區剪枝,不會建立新索引。如果不是,為保證查詢效能,系統會自動建立一個新的本地索引。

如何查看資料庫是AUTO模式還是DRDS模式?

執行SHOW CREATE DATABASE <database_name>,返回結果中MODE屬性即為資料庫模式。