mysql按月进行表分区

数据库 mysql 单表数据量达到千万、亿级,可以通过分表与表分区提升服务性能。

现有表accounting,4亿条数据,数据访问方式为insert与select,select为按月访问,为减少数据与程序变更,采用表分区的方式。

 

 

数据表create语句:

CREATE TABLE `accounting` (
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`nas` varchar(16) NOT NULL DEFAULT '',
`uid` varchar(20) NOT NULL DEFAULT '',
`terminal` varchar(20) DEFAULT NULL,
`client_ip` varchar(16) NOT NULL DEFAULT '',
`type` varchar(20) DEFAULT NULL,
`service` varchar(20) DEFAULT NULL,
`priv_lvl` int(2) DEFAULT NULL,
`cmd` varchar(255) DEFAULT NULL,
`elapsed_time` int(6) DEFAULT NULL,
`bytes_in` int(10) DEFAULT NULL,
`bytes_out` int(10) DEFAULT NULL,
`id` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`, `date`),                                      按月分表,date需要为primary key
KEY `date_index` (`date`),
KEY `acct_index` (`uid`),
KEY `nas_index` (`nas`),
KEY `client_index` (`client_ip`),
KEY `nas_date` (`date`,`nas`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1

PARTITION BY RANGE (to_days(date)) (
PARTITION p201409 VALUES LESS THAN (to_days('2014-10-01')),
PARTITION p201410 VALUES LESS THAN (to_days('2014-11-01')),
PARTITION p201411 VALUES LESS THAN (to_days('2014-12-01')),
PARTITION p201412 VALUES LESS THAN (to_days('2015-01-01')),
PARTITION p201501 VALUES LESS THAN (to_days('2015-02-01')),
PARTITION p201502 VALUES LESS THAN (to_days('2015-03-01')),
PARTITION p201503 VALUES LESS THAN (to_days('2015-04-01')),
PARTITION p201504 VALUES LESS THAN (to_days('2015-05-01')),
PARTITION p201505 VALUES LESS THAN (to_days('2015-06-01')),
PARTITION p201506 VALUES LESS THAN (to_days('2015-07-01')),
PARTITION p201507 VALUES LESS THAN (to_days('2015-08-01')),
PARTITION p201508 VALUES LESS THAN (to_days('2015-09-01')),
PARTITION p201509 VALUES LESS THAN (to_days('2015-10-01')),
PARTITION p201510 VALUES LESS THAN (to_days('2015-11-01')),
PARTITION p201511 VALUES LESS THAN (to_days('2015-12-01')),
PARTITION p201512 VALUES LESS THAN (to_days('2016-01-01')),
PARTITION p201601 VALUES LESS THAN (to_days('2016-02-01')),
PARTITION p201602 VALUES LESS THAN (to_days('2016-03-01')),
PARTITION p201603 VALUES LESS THAN (to_days('2016-04-01')),
PARTITION p201604 VALUES LESS THAN (to_days('2016-05-01')),
PARTITION p201605 VALUES LESS THAN (to_days('2016-06-01')),
PARTITION p201606 VALUES LESS THAN (to_days('2016-07-01')),
PARTITION p201607 VALUES LESS THAN (to_days('2016-08-01')),
PARTITION p201608 VALUES LESS THAN (to_days('2016-09-01')),
PARTITION p201609 VALUES LESS THAN (to_days('2016-10-01')),
PARTITION p201610 VALUES LESS THAN (to_days('2016-11-01')),
PARTITION p201611 VALUES LESS THAN (to_days('2016-12-01')),
PARTITION p201612 VALUES LESS THAN (to_days('2017-01-01')),
PARTITION p201701 VALUES LESS THAN (to_days('2017-02-01')),
PARTITION p201702 VALUES LESS THAN (to_days('2017-03-01')),
PARTITION p201703 VALUES LESS THAN (to_days('2017-04-01')),
PARTITION p201704 VALUES LESS THAN (to_days('2017-05-01')),
PARTITION p201705 VALUES LESS THAN (to_days('2017-06-01')),
PARTITION p201706 VALUES LESS THAN (to_days('2017-07-01')),
PARTITION p201707 VALUES LESS THAN (to_days('2017-08-01')),
PARTITION p201708 VALUES LESS THAN (to_days('2017-09-01')),
PARTITION p201709 VALUES LESS THAN (to_days('2017-10-01')),
PARTITION p201710 VALUES LESS THAN (to_days('2017-11-01')),
PARTITION p201711 VALUES LESS THAN (to_days('2017-12-01')),
PARTITION p201712 VALUES LESS THAN (to_days('2018-01-01')),
PARTITION p201801 VALUES LESS THAN (to_days('2018-02-01')),
PARTITION p201802 VALUES LESS THAN (to_days('2018-03-01')),
PARTITION p201803 VALUES LESS THAN (to_days('2018-04-01')),
PARTITION p201804 VALUES LESS THAN (to_days('2018-05-01')),
PARTITION p201805 VALUES LESS THAN (to_days('2018-06-01')),
PARTITION p201806 VALUES LESS THAN (to_days('2018-07-01')),
PARTITION p201807 VALUES LESS THAN (to_days('2018-08-01')),
PARTITION p201808 VALUES LESS THAN (to_days('2018-09-01')),
PARTITION p201809 VALUES LESS THAN (to_days('2018-10-01')),
PARTITION p201810 VALUES LESS THAN (to_days('2018-11-01')),
PARTITION p201811 VALUES LESS THAN (to_days('2018-12-01')),
PARTITION p201812 VALUES LESS THAN (to_days('2019-01-01')),
PARTITION p2019 VALUES LESS THAN (MAXVALUE) )
;

 

 

为了使用分区功能,进行查询的语句需与创建分区方式的一致:

错误:explain select * from accounting where date="2014-09-25 15:01:59";    发现访问方法为 ALL,效率最低,索引等也是NULL

正确:explain select count(*) from accounting where date < date("2014-09-26"); 

         

rows代表将要扫描的条数,如过选择了某个月的条件,那么将扫描具体月份的MYD。此时如果where中再有条件(column有索引),type将变为ref,或者:

explain select * from accounting where date = date('2015-05-01 01:23:34');

((1L, 'SIMPLE', 'accounting', 'ref', 'date_index,nas_date', 'date_index', '8', 'const', 1L, ''),)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 中,可以使用分区来提高查询性能和管理数据的效率。如果你需要按自动创建分区,可以使用 MySQL 事件调度器(Event Scheduler)和存储过程(Stored Procedure)来实现。 以下是一个示例存储过程,用于创建按分区: ``` DELIMITER $$ CREATE PROCEDURE create_monthly_partitions() BEGIN DECLARE start_date DATE; DECLARE end_date DATE; SET start_date = '2022-01-01'; -- 分区开始日期 SET end_date = DATE_ADD(CURDATE(), INTERVAL 1 MONTH); -- 下一个的第一天 WHILE start_date < end_date DO SET @sql = CONCAT('ALTER TABLE my_table ADD PARTITION (PARTITION p', DATE_FORMAT(start_date, '%Y%m'), ' VALUES LESS THAN (TO_DAYS(\'', DATE_FORMAT(DATE_ADD(start_date, INTERVAL 1 MONTH), '%Y-%m-%d'), '\')))'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET start_date = DATE_ADD(start_date, INTERVAL 1 MONTH); END WHILE; END$$ DELIMITER ; ``` 这个存储过程会创建从当前月份开始到下一个月份的所有分区,每个分区以年份和月份为名称,例如 p202201、p202202、p202203 等等。 然后,你可以使用事件调度器来定期运行这个存储过程,以便自动创建新的分区。以下是一个示例事件,每的第一天凌晨 1 点运行: ``` CREATE EVENT create_monthly_partitions_event ON SCHEDULE EVERY 1 MONTH STARTS DATE_ADD(CURDATE(), INTERVAL 1 DAY) ON COMPLETION PRESERVE DO CALL create_monthly_partitions(); ``` 这个事件会在每的第一天凌晨 1 点运行,调用上面创建的存储过程来创建新的分区。 请注意,分区需要使用特定的语法来查询和管理数据,因此在使用分区时,请确保你已经理解了它们的概念和使用方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值