mysql普通表转换分区表_将mysql非分区表转换为分区表

查看表的分布状况

mysql> select count(*) from  justin;

+----------+

| count(*) |

+----------+

|  5845246 |

+----------+

1 row in set (0.00 sec)

mysql> select month(create_time),count(*) from justin group by  month(create_time);

+-----------------------+----------+

| month(create_time) | count(*) |

+-----------------------+----------+

|                     1 |  1128520 |

|                    11 |  1574965 |

|                    12 |  3141750 |

+-----------------------+----------+

3 rows in set (6.93 sec)

考虑以create_time为分区键建立分区表

第一步  创建中间表,以主键id和分区列为联合主键

CREATE TABLE `temp_justin` (

`id` bigint(1) NOT NULL AUTO_INCREMENT COMMENT '流水号,自增',

`create_time` datetime DEFAULT NULL COMMENT '订单日志创建时间(建立索引)',

PRIMARY KEY (`id`,`create_time`),

) ENGINE=MyISAM AUTO_INCREMENT=6000000 DEFAULT CHARSET=utf8;

表已经存在580多万记录并且不断在增长,因此中间表初始的id值设置成6000000

增加分区,以月为单位

alter table temp_justin partition by range(to_days(create_time))

(

partition p1012 values less than (to_days('2011-01-01')),

partition p1101 values less than (to_days('2011-02-01')),

partition p1102 values less than (to_days('2011-03-01')),

partition p1103 values less than (to_days('2011-04-01')),

partition p1104 values less than (to_days('2011-05-01')),

partition p1105 values less than (to_days('2011-06-01')),

partition p1106 values less than (to_days('2011-07-01')),

partition p1107 values less than (to_days('2011-08-01')),

partition p1108 values less than (to_days('2011-09-01')),

partition p1109 values less than (to_days('2011-10-01')),

partition p11010 values less than (to_days('2011-11-01')),

partition p11011 values less than (to_days('2011-12-01')),

partition p11012 values less than (to_days('2012-01-01'))

);

第二步 重命名表

Alter table justin rename to justin_bak_110113;

Alter table temp_justin rename to justin;

第三步 同步数据

Insert into justin select * from temp_justin;

表里已经存在将近600万条记录,如此批量导入数据会对数据库性能影响很大。

每一万条提交一次,sleep 2s ,53万数据总耗时2 min 39.67 sec。

mysql> create procedure cp_data()

-> begin

-> declare i int;

-> set i=0;

-> while i<60 do

-> insert into justin

-> select * from justin_bak_110113

-> where id >= i*10000 and  id

-> set i=i+1;

-> select sleep(2);

-> end while;

-> end||

Query OK, 0 rows affected (0.04 sec)

mysql>

mysql> delete from justin;

-> ||

Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

mysql> call cp_data();

+----------+

| sleep(2) |

+----------+

|        0 |

+----------+

1 row in set (2 min 39.67 sec)

Query OK, 0 rows affected (2 min 39.67 sec)

mysql> select count(*) from justin;

+----------+

| count(*) |

+----------+

|   525031 |

+----------+

1 row in set (0.00 sec)

查看执行计划,使用了分区扫描

mysql> explain

-> select count(*) from justin where create_time

-> <='2011-01-13' and create_time>'2011-01-04';

+----+-------------+--------------------+-------+---------------+---------+---------+------+--------+--------------------------+

| id | select_type | table              | type  | possible_keys | key     | key_len | ref  | rows   | Extra                    |

+----+-------------+--------------------+-------+---------------+---------+---------+------+--------+--------------------------+

|  1 | SIMPLE      | justin | index | NULL          | PRIMARY | 16      | NULL | 525031 | Using where; Using index |

+----+-------------+--------------------+-------+---------------+---------+---------+------+--------+--------------------------+

1 row in set (0.00 sec)

mysql> explain

-> partitions

-> select count(*) from justin where create_time

-> <='2011-01-13' and create_time>'2011-01-04';

+----+-------------+--------------------+-------------+-------+---------------+---------+---------+------+--------+--------------------------+

| id | select_type | table              | partitions  | type  | possible_keys | key     | key_len | ref  | rows   | Extra                    |

+----+-------------+--------------------+-------------+-------+---------------+---------+---------+------+--------+--------------------------+

|  1 | SIMPLE      | justin | p1012,p1101 | index | NULL          | PRIMARY | 16      | NULL | 525031 | Using where; Using index |

+----+-------------+--------------------+-------------+-------+---------------+---------+---------+------+--------+--------------------------+

1 row in set (0.00 sec)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您解答这个问题。 MySQL分区表可以提高查询性能,并且可以通过按时间范围进行自动分区,以便更好地管理和维护数据。下面是按天执行分区表SQL的步骤: 1. 创建分区表 您可以使用以下命令创建一个按天分区的: ``` CREATE TABLE mytable ( id INT NOT NULL, created_at TIMESTAMP NOT NULL ) PARTITION BY RANGE(TO_DAYS(created_at)) ( PARTITION p0 VALUES LESS THAN (TO_DAYS('2022-01-01')), PARTITION p1 VALUES LESS THAN (TO_DAYS('2022-01-02')), PARTITION p2 VALUES LESS THAN (TO_DAYS('2022-01-03')), ... PARTITION pn VALUES LESS THAN MAXVALUE ); ``` 这将创建一个名为“mytable”的分区表,其中“created_at”列将用于分区,分区将按天进行。您需要为每个分区指定值范围,例如“p0”分区包含所有在“2022-01-01”之前创建的记录。 2. 创建分区维护事件 您可以创建一个事件,定期检查并创建新的分区。以下是一个示例事件: ``` CREATE EVENT partition_maintenance ON SCHEDULE EVERY 1 DAY DO ALTER TABLE mytable ADD PARTITION ( PARTITION pmax VALUES LESS THAN MAXVALUE ); ``` 这将创建一个名为“partition_maintenance”的事件,每天运行一次,它将在“mytable”中创建一个新的分区。 3. 自动分区 您可以在中插入数据时自动创建分区。以下是一个示例触发器: ``` CREATE TRIGGER partition_insert BEFORE INSERT ON mytable FOR EACH ROW BEGIN DECLARE partition_name VARCHAR(20); SET partition_name = CONCAT('p', DATE_FORMAT(NEW.created_at, '%Y%m%d')); SET @partition_sql = CONCAT('PARTITION ', partition_name, ' VALUES LESS THAN (TO_DAYS(\'', DATE_ADD(DATE(NEW.created_at), INTERVAL 1 DAY), '\'))'); SET @sql = CONCAT('ALTER TABLE mytable ADD ', @partition_sql); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END; ``` 这将创建一个名为“partition_insert”的触发器,在插入新记录时自动创建新的分区。该触发器将使用新记录的“created_at”值计算分区名称,并为该名称创建一个新的分区。 总之,以上是按天执行分区表SQL的步骤,希望对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值