mysql重建表分区并保留数据的方法

本文介绍了一种MySQL表分区重构的方法,通过创建新表并复制原始数据来实现分区更新,同时保持原有数据完整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文介绍mysql重建表分区并保留数据的方法,mysql的表分区(partition)可以把一个表的记录分开多个区去存储,查询时可根据查询的条件在对应的分区搜寻,而不需要整表查询,提高查询效率。

有分区的表与没有分区的表使用上没有太大的区别,但如果要对表进行重新分区,删除分区重建会删除数据,因此不可直接进行操作,需要使用一些特别的处理实现。

mysql重建表分区并保留数据的方法:

1.创建与原始表一样结构的新表,新分区。
2.将原始表中数据复制到新表。
3.删除原始表。
4.将新表名称改为原始表名称。

实例:

日志表原始结构如下,按id分区。

CREATE DATABASE `test`;

use `test`;

CREATE TABLE `log` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `content` text NOT NULL COMMENT '内容',
 `status` tinyint(3) unsigned NOT NULL COMMENT '记录状态',
 `addtime` int(11) unsigned NOT NULL COMMENT '添加时间',
 `lastmodify` int(11) unsigned NOT NULL COMMENT '最后修改时间',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (id)
(PARTITION p10w VALUES LESS THAN (100000) ENGINE = InnoDB,
PARTITION p20w VALUES LESS THAN (200000) ENGINE = InnoDB,
PARTITION p50w VALUES LESS THAN (500000) ENGINE = InnoDB,
PARTITION p100w VALUES LESS THAN (1000000) ENGINE = InnoDB,
PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */;

insert into `log`(content,status,addtime,lastmodify) 
values('content1',1, unix_timestamp('2018-01-11 00:00:00'), unix_timestamp('2018-01-11 00:00:00')),
('content2',1, unix_timestamp('2018-02-22 00:00:00'), unix_timestamp('2018-02-22 00:00:00')),
('content3',1, unix_timestamp('2018-03-31 00:00:00'), unix_timestamp('2018-03-31 00:00:00'));

查看数据分区分布

SELECT PARTITION_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 'log';

+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p10w           |          3 |
| p20w           |          0 |
| p50w           |          0 |
| p100w          |          0 |
| pmax           |          0 |
+----------------+------------+

 
日志数据需要按时间进行搜寻,因此需要按日志时间重建分区

1.创建log2,按时间分区(每月1个分区)

CREATE TABLE `log2` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `content` text NOT NULL COMMENT '内容',
 `status` tinyint(3) unsigned NOT NULL COMMENT '记录状态',
 `addtime` int(11) unsigned NOT NULL COMMENT '添加时间',
 `lastmodify` int(11) unsigned NOT NULL COMMENT '最后修改时间',
 PRIMARY KEY (`id`,`addtime`),
 KEY `id`(`id`),
 KEY `addtime`(`addtime`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (addtime)
(PARTITION p201801 VALUES LESS THAN (unix_timestamp('2018-02-01 00:00:00')) ENGINE = InnoDB,
PARTITION p201802 VALUES LESS THAN (unix_timestamp('2018-03-01 00:00:00')) ENGINE = InnoDB,
PARTITION p201803 VALUES LESS THAN (unix_timestamp('2018-04-01 00:00:00')) ENGINE = InnoDB,
PARTITION p201804 VALUES LESS THAN (unix_timestamp('2018-05-01 00:00:00')) ENGINE = InnoDB,
PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */;

 
2.将log的数据复制到log2

insert into `log2` select * from `log`;

 
3.删除log表

drop table `log`;

 
4.将log2表改名为log

rename table `log2` to `log`;

 
执行后查看数据分区分布

SELECT PARTITION_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA='test' AND TABLE_NAME = 'log';

+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p201801        |          1 |
| p201802        |          1 |
| p201803        |          1 |
| p201804        |          0 |
| pmax           |          0 |
+----------------+------------+

可以看到log表的数据已经按新分区存储。

### 增加基于月份的分区MySQL 中,可以使用 `RANGE` 或者 `LIST COLUMNS` 的方式来创建基于日期列(通常是时间戳或者日期类型的列)的分区。以下是具体的实现方法: #### 创建带月分区的表 如果要为一张新表设置基于月份的分区,可以在建表语句中指定分区策略。例如,假设有一张记录日志的表 `log_table`,其中有一个名为 `create_time` 的字段表示每条记录的时间戳。 ```sql CREATE TABLE log_table ( id INT NOT NULL AUTO_INCREMENT, message TEXT, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id, create_time) -- 主键必须包含分区键 ) PARTITION BY RANGE (TO_DAYS(create_time)) ( PARTITION p2023_01 VALUES LESS THAN (TO_DAYS('2023-02-01')), PARTITION p2023_02 VALUES LESS THAN (TO_DAYS('2023-03-01')), PARTITION p2023_03 VALUES LESS THAN (TO_DAYS('2023-04-01')) ); ``` 此示例中的 `TO_DAYS()` 函数用于将日期转换成天数以便于范围划分[^1]。 #### 对现有表添加月分区 如果已经存在一张表而希望为其添加基于月份的分区,则需要先将其导出到一个新的带有分区定义的新表中。具体过程如下: 1. **备份原始数据** 首先确保当前的数据被安全保存下来。 2. **重新创建支持分区结构的新表** 使用类似于上述的方法构建新的分区表。 3. **迁移旧数据至新表** 将原表中的所有数据导入新建好的分区表里。 4. **替换原有表名** 当确认无误之后,可以用新表替代原来的表名称。 需要注意的是,在某些情况下可能还需要调整应用层面对应逻辑以适应这种变化[^3]。 另外值得注意的一点是关于索引方面的问题。当采用分区技术时,每一个单独的子分区都会维护自己独立的一套次级索引体系;因此即使总体上看似乎增加了额外开销但实际上由于查询通常只涉及部分而非全部分区内存从而提高了检索效率[^1]。 最后提醒一点就是尽量避免直接修改已存在的大型生产环境下的数据库对象除非绝对必要且经过充分测试验证可行后再行动以免造成不可预料后果影响业务正常运行状态[^4]。 ```sql -- 示例:向已有表添加分区功能前需重建表 ALTER TABLE existing_log_table RENAME TO old_existing_log_table; CREATE TABLE new_log_table LIKE old_existing_log_table; ALTER TABLE new_log_table ADD PRIMARY KEY(id, create_time); INSERT INTO new_log_table SELECT * FROM old_existing_log_table ORDER BY create_time; RENAME TABLE existing_log_table TO backup_log_table, new_log_table TO existing_log_table; ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值