当单张普通表的数据量超过10亿行或1 TB时,建议采用分区表。本文将介绍如何使用ALTER
语法将单张普通表转换为分区表。
前提条件
在将普通表转换为分区表时,若普通表存在主键(Primary Key)和唯一键(Unique Key),则主键和唯一键均需包含分区键(Partition Key)字段。以确保每个分区内数据及全局数据的唯一性。详细示例,请参见示例。
例如:
若按单列
order_id
进行分区,则主键和唯一键应包含order_id
(如PRIMARY KEY(id, order_id)
)。若按多列
region_id
和order_date
进行分区,则主键和唯一键应包含region_id
和order_date
(如PRIMARY KEY(id, region_id, order_date)
)。
注意事项
普通表转换为分区表的过程中,所有的数据都需要重新进行读写,属于COPY DDL操作。因此,转换时间较长,且整个转换过程会阻塞当前表上的所有DML操作。
说明COPY DDL执行算法是需要将表中所有的数据复制到新表中。在数据复制期间,会持有原表的SNW(SHARED_NO_WRITE)锁。因此,在执行DDL操作期间仅支持读操作,不允许执行并发写入操作,对业务影响较大。更多信息,请参见DDL执行算法。
如果需要按照时间做RANGE分区,并且需要将所有数据放在一个历史分区中,请参见普通表快速转换为RANGE分区表。
支持转换的分区表类型
所有的分区表类型(如HASH、RANGE以及LIST等)均支持普通表转换分区表操作。详细分区表类型请参见分区表类型及使用说明和INTERVAL RANGE分区。
语法
ALTER TABLE table_name
PARTITION BY RANGE {(expr) | COLUMNS(column_list)}
(partition_definition [, partition_definition] ...);
其中,partition_definition
的定义与各个类型的分区表中的partition_definition
保持一致,支持二级分区。
PolarDB MySQL版支持的分区表类型及使用,请参见分区表类型及使用说明。
示例
单列分区
此处以普通表test_users
为例,为您演示如何将普通表转换为分区表。
创建普通表
test_users
,并插入数据。CREATE TABLE test_users ( id INT AUTO_INCREMENT, region_id INT NOT NULL, -- 分区键 email VARCHAR(100) NOT NULL, name VARCHAR(50), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id, region_id), -- 主键必须包含分区键字段 UNIQUE KEY (email, region_id) -- 唯一键必须包含分区键字段 );
INSERT INTO test_users (region_id, email, name) VALUES (1, 'alice@example.com', 'Alice'), (2, 'bob@example.com', 'Bob'), (3, 'charlie@example.com', 'Charlie');
将普通表
test_users
转换为分区表。转换为LIST分区表。更多信息,请参见LIST。
ALTER TABLE test_users PARTITION BY LIST (region_id) ( PARTITION p_east VALUES IN (1, 2), -- region_id为1或2的数据到p_east PARTITION p_west VALUES IN (3) -- region_id为3的数据到p_west );
转换为HASH分区表。更多信息,请参见HASH。
ALTER TABLE test_users PARTITION BY HASH(region_id) PARTITIONS 4; -- 分为4个哈希分区
转换为RANGE分区表。更多信息,请参见RANGE。
ALTER TABLE test_users PARTITION BY RANGE (region_id) ( PARTITION p0 VALUES LESS THAN (2), -- region_id < 2 PARTITION p1 VALUES LESS THAN (3), -- 2 ≤ region_id < 3 PARTITION p2 VALUES LESS THAN MAXVALUE );
多列分区
此处以普通表orders
为例,为您演示如何将普通表转换为分区表。
创建普通表
orders
,并插入数据。CREATE TABLE orders ( order_id INT AUTO_INCREMENT, region_id INT NOT NULL, -- 分区键字段1 order_date DATE NOT NULL, -- 分区键字段2 customer_id INT, amount DECIMAL(10,2), PRIMARY KEY (order_id, region_id, order_date), -- 主键必须包含所有分区键字段 UNIQUE KEY (customer_id, order_id, region_id, order_date) -- 唯一键必须包含所有分区键字段 );
INSERT INTO orders (region_id, order_date, customer_id, amount) VALUES (1, '2022-12-31', 1001, 99.99), (1, '2023-05-01', 1002, 199.99), (2, '2023-06-01', 1003, 299.99);
将普通表
orders
转换为RANGE分区表。更多信息,请参见RANGE。ALTER TABLE orders PARTITION BY RANGE COLUMNS(region_id, order_date) ( PARTITION p0 VALUES LESS THAN (1, '2023-01-01'), -- region_id < 1 或 region_id=1 且 order_date < '2023-01-01' PARTITION p1 VALUES LESS THAN (2, '2024-01-01'), -- region_id < 2 或 region_id=2 且 order_date < '2024-01-01' PARTITION p2 VALUES LESS THAN (MAXVALUE, MAXVALUE) );
常见问题
相关文档
INTERVAL RANGE分区:RANGE分区的扩展。当新插入的数据超出现有分区的范围时,该分区允许数据库自动创建新的分区。
普通表快速转换为RANGE分区表:如果需要按照时间做RANGE分区,并且需要将所有数据放在一个历史分区中。
专家面对面
如需了解更多关于普通表转换为分区表的内容,可通过钉钉搜索群号入群咨询。您可以直接@群内专家,并附上您要咨询的问题。
钉钉群号:24490017825。