mysql按照天分区月表

37 篇文章 0 订阅
11 篇文章 4 订阅

背景,每天需要向mysql中插入大概5KW数据,数据主要是插入,与查询基本不会update,由于量大需要查询因此想创建天表,但是缺点在于:

  1. 每天一张表也比较麻烦

  2. 假设现在要查询几天的数据,还得查询多张表,最终合并查询结果,这一点十分麻烦

这时可以考虑用一张月表,每一天的数据一个分区表,而分区表对于用户是透明的。

下面给出一个简单的示例,仅仅为了展示:

CREATE TABLE `audio_rec_ret_2017_11` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `ftime` datetime NOT NULL,
  PRIMARY KEY (`id`,`ftime`),
  KEY `ftime_idx` (`ftime`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
PARTITION BY RANGE (TO_DAYS(ftime))
(    PARTITION p20171101 VALUES LESS THAN (TO_DAYS('2017-11-02')) ENGINE = InnoDB,
    PARTITION p20171102 VALUES LESS THAN (TO_DAYS('2017-11-03')) ENGINE = InnoDB,
    PARTITION p20171103 VALUES LESS THAN (TO_DAYS('2017-11-04')) ENGINE = InnoDB,
    PARTITION p20171104 VALUES LESS THAN (TO_DAYS('2017-11-05')) ENGINE = InnoDB,
    PARTITION p20171105 VALUES LESS THAN (TO_DAYS('2017-11-06')) ENGINE = InnoDB,
    PARTITION p20171106 VALUES LESS THAN (TO_DAYS('2017-11-07')) ENGINE = InnoDB,
    PARTITION p20171107 VALUES LESS THAN (TO_DAYS('2017-11-08')) ENGINE = InnoDB,
    PARTITION p20171108 VALUES LESS THAN (TO_DAYS('2017-11-09')) ENGINE = InnoDB,
    PARTITION p20171109 VALUES LESS THAN (TO_DAYS('2017-11-10')) ENGINE = InnoDB
);

插入如下数据

insert into springdemo.audio_rec_ret_2017_11(ftime)
values('2017-11-1 10:10:10'),
('2017-11-2 10:10:10'),
('2017-11-3 10:10:10'),
('2017-11-4 10:10:10'),
('2017-11-5 10:10:10'),
('2017-11-6 10:10:10');

看下我们的查询结果:

explain partitions 
select * from springdemo.audio_rec_ret_2017_11
where ftime between '2017-11-4 0:0:0' and '2017-11-5 23:59:59';

这里写图片描述

可以看到只遍历了,两个分区表,只扫描了2行,而不是扫描所有的行。

上面的按照月每天一张表的,如下数据,每次写的很麻烦,于是考虑使用python生成

 PARTITION p20171106 VALUES LESS THAN (TO_DAYS('2017-11-07')) ENGINE = InnoDB,

生成代码如下:

def tb_partition_sql():
    """
    mysql partition table by day in month
    :return:
    """
    sql = """PARTITION p%s VALUES LESS THAN (TO_DAYS('%s')) ENGINE = InnoDB,"""
    d1 = datetime.date(2017, 12, 1)
    d2 = datetime.date(2017, 12, 31)
    days = [d1 + datetime.timedelta(days=x) for x in range((d2-d1).days + 2)]
    # print len(days)
    for i in xrange(len(days) - 1):
        s1 = days[i].strftime('%Y%m%d')
        s2 = days[i + 1].strftime('%Y-%m-%d')
        print sql % (s1, s2)

这里写图片描述

代码见本人的github

生成完成之后,复制到mysql的语句中即可。

CREATE TABLE `audio_rec_ret_2017_12` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `ftime` datetime NOT NULL,
  PRIMARY KEY (`id`,`ftime`),
  KEY `ftime_idx` (`ftime`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
PARTITION BY RANGE (TO_DAYS(ftime))(

//复制到这里


);

使用的过程中,查询的时候一定要加上时间范围这样可以大大减少查询时间。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值