MySQL之按月拆分主表并按月分表写入数据提高数据查询速度

使用场景:

主表数据量特别大,为了提高查询的速度,可以考虑按月进行分表,要求就是当月的数据到当月表查询,上月的数据到上月表查询,当天的数据到主表来查询。这样在一定程度上也是提高了数据的查询速度

过程演示:

1.创建总表:

CREATE TABLE `zong_biao` (
  `id` int(8) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `password` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `create_time` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
 `day` date NOT NULL DEFAULT ‘0000-00-00‘ COMMENT ‘日期‘,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

2.创建定时器:

当前时间1分钟后,每2分钟写入一条数据到zong_biao,为了演示,要保证主表里面一直有数据定时在写入

delimiter $$
create event event_1
on schedule every 2 MINUTE  STARTS   CURRENT_TIMESTAMP + INTERVAL 1 MINUTE
COMMENT ‘xiaowu create‘
do
    BEGIN
           insert into test.zong_biao(username,password,create_time,day) values("李四","tomcat",now(),curdate());
    END $$
delimiter ;

3.按月对主表进行分表拆分数据

3.1建立上月表和本月表

mysql> create table biao_lastmonth like zong_biao;

Query OK, 0 rows affected

mysql>  create table biao_month like zong_biao;

Query OK, 0 rows affected

3.2.创建一个表来记录是否是1号,数据写入是否成功:

Create Table: CREATE TABLE `dr_call_time` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `c_datetime` datetime NOT NULL COMMENT ‘执行时间‘,
  `type` tinyint(4) NOT NULL DEFAULT ‘0‘ COMMENT ‘是否为1号,默认为0,即不是1号‘,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8

mysql> select * from dr_call_time;
+----+---------------------+------+
| id | c_datetime | type |
+----+---------------------+------+
| 1 | 2018-09-24 02:00:00 | 0 |
| 2 | 2018-09-25 02:00:00 | 0 |
| 3 | 2018-09-26 02:00:00 | 0 |
| 4 | 2018-09-27 02:00:00 | 0 |
| 5 | 2018-09-28 02:00:00 | 0 |
| 6 | 2018-09-29 02:00:00 | 0 |
| 7 | 2018-09-30 02:00:00 | 0 |
| 8 | 2018-10-01 02:00:01 | 1 |
| 9 | 2018-10-02 02:00:00 | 0 |
+----+---------------------+------+
9 rows in set (0.00 sec)

3.3. 建立存储过程


/*每月1号 清空上月表,清空本月表;如果不是每月1号,则把昨天的数据插入本月数据表中*/
delimiter //
CREATE PROCEDURE p_dr_stats()
BEGIN
    declare v_day int;
  declare v_yesterday date;

set v_day = day(curdate());
set v_yesterday = date_sub(current_date(),interval 1 day);
select v_day;
/*select v_yesterday;*/

/*每月第一天 清空本月表和上月表;如果不是本月第一天,则把昨天的数据插入本月数据表中*/
if v_day = 1 then
   truncate table biao_lastmonth;
   truncate table biao_month;
   insert into biao_lastmonth select * from zong_biao where day >= date_add(curdate()-day(curdate())+1,interval -1 month) and day < date_add(curdate(), interval - day(curdate()) + 1 day);
   insert into dr_call_time(c_datetime,type) values(now(),1);  /* 用于记录该过程是否已执行*/
else
    insert into biao_month select * from zong_biao where day >= v_yesterday and day < curdate();
    insert into dr_call_time(c_datetime) values(now());
end if;
end //
delimiter ;

3.4 建立定时任务event

/*从2018-09-24 02:00:00开始,每天凌晨2:00执行上面的3.3的存储过程
delimiter //
CREATE EVENT e_test
ON SCHEDULE EVERY 1 day STARTS TIMESTAMP ‘2018-09-24 02:00:00‘
ON COMPLETION PRESERVE
DO
BEGIN
CALL p_dr_stats();
END//
delimiter ; 

查看记录是否是1号的表,了解event定时器和储存过程的执行状态

mysql> select * from dr_call_time;
+----+---------------------+------+
| id | c_datetime          | type |
+----+---------------------+------+
|  1 | 2018-09-24 02:00:00 |    0 |
|  2 | 2018-09-25 02:00:00 |    0 |
|  3 | 2018-09-26 02:00:00 |    0 |
|  4 | 2018-09-27 02:00:00 |    0 |
|  5 | 2018-09-28 02:00:00 |    0 |
|  6 | 2018-09-29 02:00:00 |    0 |
|  7 | 2018-09-30 02:00:00 |    0 |
|  8 | 2018-10-01 02:00:01 |    1 |
|  9 | 2018-10-02 02:00:00 |    0 |
+----+---------------------+------+
9 rows in set (0.00 sec)

到此处演示完毕,测试都是没问题的

3.5查看创建存储过程的语句


mysql> show create procedure p_dr_stats\G
*************************** 1. row ***************************
           Procedure: p_dr_stats
            sql_mode: STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
    Create Procedure: CREATE DEFINER=`root`@`localhost` PROCEDURE `p_dr_stats`()
BEGIN
declare v_day int;
  declare v_yesterday date;

set v_day = day(curdate());
set v_yesterday = date_sub(current_date(),interval 1 day);
select v_day;

if v_day = 1 then
   truncate table biao_lastmonth;
   truncate table biao_month;
   insert into biao_lastmonth select * from zong_biao where day >= date_add(curdate()-day(curdate())+1,interval -1 month) and day < date_add(curdate(), interval - day(curdate()) + 1 day);
   insert into dr_call_time(c_datetime,type) values(now(),1);  

else
    insert into biao_month select * from zong_biao where day >= v_yesterday and day < curdate();
    insert into dr_call_time(c_datetime) values(now());
end if;
end
character_set_client: utf8
collation_connection: utf8_general_ci
  Database Collation: utf8_general_ci
1 row in set (0.00 sec)

mysql> 

到此处MySQL之按月拆分主表并按月分表写入数据已经演示完毕了,欢迎伙伴们留言一起交流学习。

原文地址:http://blog.51cto.com/wujianwei/2296662

时间: 2024-10-07 19:16:37

MySQL之按月拆分主表并按月分表写入数据提高数据查询速度的相关文章

MySQL优化分库分表,为什么要分表,分表以后如何进行排序查询,业务如何设计?

MySQL优化分库分表,为什么要分表,分表以后如何进行排序查询,业务如何设计? 昨天面试新人的时候,遇到了这么一个问题,按照自己的想法大体聊了一些,但大多是感性的,并没有完整的了解why and how. 今天查了一些相关的资料,包括<MySQL性能调优与架构设计>.<高性能Mysql>,慢慢的整体理解,请大家指正. 之一,为什么要分表? 分表,按形式,有水平分表和主附分表.水平分表常见于按ID取模或者按日期将相同表结构的内容散列到不同的表上,主附分表常见于有对应关系的多张表,通过

MySQL如何实现分库分表,如何提高查询效率

本人没有做过电商平台,但了解其中的道道,今天闲来无事,说说其中的道道.下边我要开始表演了. 在大型电商网站中,随着业务的增多,数据库中的数据量也是与日俱增,这时候就要将数据库进行分库分表了. 1.如何分库分表? 两种解决方案:垂直拆分.水平拆分 垂直拆分:根据业务进行拆分,比如可以将一张表中的多个字段拆成两张表,一张是不经常更改的,一张是经常改的. 水平拆分:即根据表来进行分割:比如user表可以拆分为user0,.user1.user2.user3.user4等 2.分库分表之后如何实现联合查

Mysql数据库一个小程序实现自动创建分表。

每当跨月的时候也是系统出问题最多的时候,没有表和字段缺失是两个最常见的错误. 为了解决这个问题,研究了一下mysql的 information_schema 表: information_schema这张数据表保存了MySQL服务器所有数据库的信息.如数据库名,数据库的表,表栏的数据类型与访问权限等. 再简单点,这台MySQL服务器上,到底有哪些数据库.各个数据库有哪些表,每张表的字段类型是什么,各个数据库要什么权限才能访问,等等信息都保存在information_schema表里面. OK!事

Mysql 数据库优化(三)——分区和分表【个人经验】

引:MyISAM存储引擎的表在数据库中,每一个表都被存放为三个以表名命名的物理文件. 1.首先肯定会有任何存储引擎都不可缺少的存放表结构定义信息的.frm文件, 2.另外还有.MYD和.MYI文件,分别存放了表的数据(.MYD)和索引数据(.MYI). 每个表都有且仅有这样三个文件做为MyISAM存储类型的表的存储,也就是说不管这个表有多少个索引,都是存放在同一个.MYI文件中. MyISAM支持以下三种类型的索引: 1.B-Tree索引 B-Tree索引,顾名思义,就是所有的索引节点都按照ba

在mysql中创建 oracle scott 用户的四个表及插入初始化数据

各表的字段的含义: (参考自:http://www.cnblogs.com/mchina/archive/2012/09/06/2649951.html) 1.  部门表:dept № 名称 类型 描述 1 DEPTNO NUMBER(2) 表示部门编号,由两位数字所组成 2 DNAME VARCHAR2(14) 部门名称,最多由14个字符所组成 3 LOC VARCHAR2(13) 部门所在的位置 2.  雇员表:emp № 名称 类型 描述 1 EMPNO NUMBER(4) 雇员的编号,由

3.mysql的中文问题,database级操作,表级操作,数据CRUD,分组操作,时间和日期,字符串相关函数,表的约束

 1 连接MYSQL服务器:mysql–uroot –p123456 查看中文问题 show variables like 'character%'; 2 修改mysql的字符集,退出mysql提示符界面: mysql -uroot -p--default_character_set=gbk; 3  数据库的操作:创建,查看,修改,删除 *创建: 创建一个名称为mydb1的数据库. createdatabase mydb1; 创建一个使用utf-8字符集的mydb2数据库. create d

关于mysql处理百万级以上的数据时如何提高其查询速度的方法

关于大数据量处理方法: 1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 3.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:     select id from t where num is null     可以在num上设置默认值0,确保表中num列没有null值,然后这

MySQL数据库分表分区(一)(转)

面对当今大数据存储,设想当mysql中一个表的总记录超过1000W,会出现性能的大幅度下降吗? 答案是肯定的,一个表的总记录超过1000W,在操作系统层面检索也是效率非常低的 解决方案: 目前针对海量数据的优化有两种方法: 1.大表拆小表的方式(主要有分表和分区两者技术) (1)分表技术 垂直分割 优势:降低高并发情况下,对于表的锁定. 不足:对于单表来说,随着数据库的记录增多,读写压力将进一步增大. 水平分割 如果单表的IO压力大,可以考虑用水平分割,其原理就是通过hash算法,将一张表分为N

mysql数据库分表分区

防伪码:博观而约取,厚积而薄发 为什么要分表和分区? 我们的数据库数据越来越大,随之而来的是单个表中数据太多.以至于查询书读变慢,而且 由于表的锁机制导致应用操作也搜到严重影响,出现了数据库性能瓶颈. mysql 中有一种机制是表锁定和行锁定,是为了保证数据的完整性.表锁定表示你们都不能 对这张表进行操作,必须等我对表操作完才行.行锁定也一样,别的 sql 必须等我对这条数 据操作完了,才能对这条数据进行操作.当出现这种情况时,我们可以考虑分表或分区. 1.分表 什么是分表? 分表是将一个大表按