前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MySQL时间类分区写SQL的一些注意事项

MySQL时间类分区写SQL的一些注意事项

作者头像
bisal
发布于 2022-03-02 00:52:01
发布于 2022-03-02 00:52:01
1.3K00
代码可运行
举报
运行总次数:0
代码可运行
杨老师上篇文章《MySQL时间分区的实现》介绍了时间类分区的实现方法,这篇是上篇的一个延伸,介绍基于此类分区的相关SQL编写注意事项。

对于分区表的检索无非有两种,一种是带分区键,另一种则不带分区键。一般来讲检索条件带分区键则执行速度快,不带分区键则执行速度变慢。这种结论适应于大多数场景,但不能以偏概全,要针对不同的分区表定义来写最合适的SQL语句。用分区表的目的是为了减少SQL语句检索时的记录数,如果没有达到预期效果,则分区表只能带来副作用。

接下来我列举几个经典的 SQL 语句:

细心的读者在阅读完上篇可能心中就有一些疑问,基于表ytt_p1的SQL语句如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select count(*) from ytt_pt1 where log_date >='2018-01-01' and log_date <'2019-01-01';

同样是分区表 ytt_pt1_month1 ,基于这张表的SQL语句如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select count(*) from ytt_pt1_month1 where log_date in ('2020-01-01','2020-01-02','2020-01-03','2020-01-04','2020-01-05','2020-01-06','2020-01-07','2020-01-08','2020-01-09','2020-01-10','2020-01-11','2020-01-12','2020-01-13','2020-01-14','2020-01-15');

两张表的检索需求类似,为何写法差异不小?后者为何要写成列表形式而不继续写成简单的范围检索形式?带着这点疑问,我们继续。

MySQL针对分区表有一项优化技术叫partition pruning ,翻译过来就是分区裁剪。其大致含义是MySQL会根据SQL语句的过滤条件对应的分区函数进行计算,并把计算结果穿透到底层分区表从而减小扫描记录数的一种优化策略。对于时间类型(DATE、TIMESTAMP、TIME、DATETIME),MySQL仅支持部分函数的分区裁剪:to_days、to_seconds、year、unix_timestamp。那么我们再来看之前的疑问:表ytt_pt1_month1分区函数为month,MySQL分区表虽然支持month函数,但是分区裁剪技术却不包含这个函数。接下来,分两部分来介绍本篇内容。

(1) 来体验下MySQL的分区裁剪技术,新建一张表pt_pruning:分区函数为to_days。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
create table pt_pruning (
id int,
r1 int,
r2 int,
log_date date)
partition by range(to_days(log_date))
(
 PARTITION p_01 VALUES LESS THAN (to_days('2020-02-01')) ENGINE = InnoDB,
 PARTITION p_02 VALUES LESS THAN (to_days('2020-03-01')) ENGINE = InnoDB,
 PARTITION p_03 VALUES LESS THAN (to_days('2020-04-01')) ENGINE = InnoDB,
 PARTITION p_04 VALUES LESS THAN (to_days('2020-05-01')) ENGINE = InnoDB,
 PARTITION p_05 VALUES LESS THAN (to_days('2020-06-01')) ENGINE = InnoDB,
 PARTITION p_06 VALUES LESS THAN (to_days('2020-07-01')) ENGINE = InnoDB,
 PARTITION p_07 VALUES LESS THAN (to_days('2020-08-01')) ENGINE = InnoDB,
 PARTITION p_08 VALUES LESS THAN (to_days('2020-09-01')) ENGINE = InnoDB,
 PARTITION p_09 VALUES LESS THAN (to_days('2020-10-01')) ENGINE = InnoDB,
 PARTITION p_10 VALUES LESS THAN (to_days('2020-11-01')) ENGINE = InnoDB,
 PARTITION p_11 VALUES LESS THAN (to_days('2020-12-01')) ENGINE = InnoDB,
 PARTITION p_12 VALUES LESS THAN (to_days('2021-01-01')) ENGINE = InnoDB,
 PARTITION p_max VALUES LESS THAN MAXVALUE ENGINE = InnoDB
)
此表包含2020年一整年的数据,大概100W条,此处省略造数据过程。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select min(log_date),max(log_date),count(*) from pt_pruning;
+---------------+---------------+----------+
| min(log_date) | max(log_date) | count(*) |
+---------------+---------------+----------+
| 2020-01-02    | 2020-12-31    |  1000000 |
+---------------+---------------+----------+
1 row in set (0.72 sec)
分别执行下面几条SQL:

SQL 1:求日期包含'2020-01-02'的记录条数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SQL 1:select count(*) from pt_pruning where log_date <= '2020-01-02';

SQL 2和SQL 3:求2020年1月份的记录条数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SQL 2:select count(*) from pt_pruning where log_date < '2020-02-01';

SQL 3:  select count(*) from pt_pruning where log_date between '2020-01-01' and '2020-01-31';

SQL 1和 SQL 2执行时间为0.04秒,SQL 3执行时间为0.06秒。在没有使用索引的条件下效果还是比较理想的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 select count(*) from pt_pruning where log_date <= '2020-01-02';
+----------+
| count(*) |
+----------+
|     2621 |
+----------+
1 row in set (0.04 sec)

select count(*) from pt_pruning where log_date < '2020-02-01';
+----------+
| count(*) |
+----------+
|    82410 |
+----------+
1 row in set (0.04 sec)

select count(*) from pt_pruning where log_date between '2020-01-01' and '2020-01-31';
+----------+
| count(*) |
+----------+
|    82410 |
+----------+
1 row in set (0.06 sec)
所以切记使用MySQL分区裁剪技术规定的分区函数来建立分区表,这样写SQL就会相对随意些。如果由于历史原因,分区表没有使用以上规定的分区函数,可以有以下两项可能的优化策略:

(1) 手工改 SQL 语句让其达到最优。

(2) 加 HINT 来提示 MySQL 使用具体的分区。

(2) 如果分区表使用的分区函数未满足MySQL分区裁剪技术的规则,该如何优化此类SQL语句?

为避免和上篇内容混淆,建张新表pt_month,复制表ytt_pt1_month1的表定义。表pt_month和表pt_pruning一样,存放了2020年一整年的记录,总条数也为100W。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select min(log_date),max(log_date),count(*) from pt_month;
+---------------+---------------+----------+
| min(log_date) | max(log_date) | count(*) |
+---------------+---------------+----------+
| 2020-01-02    | 2020-12-31    |  1000000 |
+---------------+---------------+----------+
1 row in set (0.72 sec)

再次执行之前的三条SQL,并把表名替换为pt_month:

SQL 1执行时间为1.26秒,相比之前慢了不少。查看执行计划,发现未使用MySQL分区裁剪技术,扫描了不必要的表分区。(这里是全部表分区)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select count(*) from pt_month where log_date <= '2020-01-02';
+----------+
| count(*) |
+----------+
|     2621 |
+----------+
1 row in set (1.26 sec)

explain 
    -> select count(*) from pt_month where log_date <= '2020-01-02'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: pt_month
   partitions: p_01,p_02,p_03,p_04,p_05,p_06,p_07,p_08,p_09,p_10,p_11,p_max
...
         rows: 992805
     filtered: 33.33
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

接下来对SQL 1进行一项简单的优化:既然是求日期为’2020-01-02‘那天的记录,那就不要使用<=来过滤,直接用=过滤:执行时间0.03秒。查看执行计划,改后的SQL直接定位到表分区p_01,达到了分区裁剪的效果。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select count(*) from pt_month where log_date = '2020-01-02';
+----------+
| count(*) |
+----------+
|     2621 |
+----------+
1 row in set (0.03 sec)

explain 
    -> select count(*) from pt_month where log_date = '2020-01-02'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: pt_month
   partitions: p_01
         type: ALL
...
         rows: 82522
     filtered: 10.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

继续执行SQL 2和SQL 3:执行时间都是1秒到2秒之间,效率很差,也未使用MySQL分区裁剪技术。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select count(*) from pt_month where log_date < '2020-02-01';
+----------+
| count(*) |
+----------+
|    82410 |
+----------+
1 row in set (1.35 sec)

select count(*) from pt_month where log_date between '2020-01-01' and '2020-01-31';
+----------+
| count(*) |
+----------+
|    82410 |
+----------+
1 row in set (1.93 sec)

来继续优化SQL 2和SQL 3,由于两个需求一致,可以把范围检索改为指定列表检索:执行时间仅为0.04秒。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select count(*) from pt_month where log_date in ('2020-01-01','2020-01-02','2020-01-03','2020-01-04','2020-01-05','2020-01-06','2020-01-07','2020-01-08','2020-01-09','2020-01-10','2020-01-11','2020-01-12','2020-01-13','2020-01-14','2020-01-15','2020-01-16','2020-01-17','2020-01-18','2020-01-19','2020-01-20','2020-01-21','2020-01-22','2020-01-23','2020-01-24','2020-01-25','2020-01-26','2020-01-27','2020-01-28','2020-01-29','2020-01-30','2020-01-31');
+----------+
| count(*) |
+----------+
|    82410 |
+----------+
1 row in set (0.04 sec)

把范围查询改为IN列表后,效率得到很大提升,查询计划显示MySQL优化器只在分区p_01上检索记录。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
   partitions: p_01
...

除了改造SQL语句,还可以给语句加HINT的方式来让MySQL使用分区裁剪技术:比如给SQL 2加上HINT后,执行时间为0.04秒,和之前改造后的语句执行效率相当。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
select count(*) from pt_month partition (p_01) where log_date < '2020-02-01';
+----------+
| count(*) |
+----------+
|    82410 |
+----------+
1 row in set (0.04 sec)

因此,如果由于历史原因分区表未使用MySQL分区裁剪技术,可以按照以下规则来手动对分区表进行裁剪优化。(查询语句必须包含分区键并且是等值查询或者是IN(OR)列表查询)具体表现形式为:

(1) select * from tbname where partition_key = value;

(2) select * from tbname 

     where partition_key in (value1,value2,...,valueN);

(3) 以上两种规则对于多表 JOIN 依然适用。

Oracle同样有分区剪裁的功能,但是不存在MySQL这种对某些函数不适用的场景,这可能就和实现的方式相关了。不同数据库之间,一些功能还是存在相同点和不同点,使用的时候,还是要知道。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022/03/01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Windows 7笔记本创建wifi热点供手机上网教程
用智能手机的朋友会发现这样一个问题,智能手机比普通手机上网更耗流量。这是因为智能手机应用(软件)丰富,而且大部分应用都会自动联网。为此,许多人每月包了上百M的流量套餐,但用的时候还是小心翼翼,生怕流量超了手机被扣费。 今天给大家介绍下Windows 7系统笔记本创建wifi热点供手机上网的方法。通过创建wifi热点,共享笔记本的有线宽带,大部分支持wifi功能的智能手机就可以通过笔记本的共享网络畅快上网了。 工具/原料 带无线网卡、支持承载网络且系统为Win7的笔记本 有线宽带/无线宽带 步骤一、查
hbbliyong
2018/03/06
5.8K0
Windows 7笔记本创建wifi热点供手机上网教程
3G上网本搭建无线路由供iPad上网
出差在外,难免遇到没wifi热点的地方,手机和平板无法上网。今年去山西出差便遇到了这个bug,经在网上查找和亲自实践,目前已修复。
阳光岛主
2019/02/19
1.3K0
3G上网本搭建无线路由供iPad上网
断网、网络卡、慢、掉线的常规解决方法
这种情况就要先了解网络的组成,一般是由,光猫、无线路由、接入端设备(电脑、手机等)组成。也有直接就一个光猫,没有接入路由器的。
简单并不简单
2019/10/24
5.2K0
断网、网络卡、慢、掉线的常规解决方法
台式计算机网线,台式电脑连接网线的是哪里 台式电脑怎么连接wifi步骤
4999或者运营商的问题,方法有哪些,我的笔记本和台式机都是10,联想启天4155,笔记本连的路由器的无线,用(wifi调试桥台式机电脑)使用脚本辅助微连接台式电脑连接信小程序跳一跳简单实用教程新人适用一wifi条龙附带资源,只有网线,另一种可能度出问题了,28访问量,什么叫做二次开发,惠普连接暗影精台式电脑连接灵5,连接对于家中台式电脑连接路由电脑怎样器还有连wifi接猫的用户,台式电脑,热门台式电脑排行,
全栈程序员站长
2022/09/13
2K0
家用无线路由器到底该怎么设置?
如今无线Wifi可以说是家家都有,我们的手机、音响、投影仪、平板电脑、笔记本电脑都在用Wifi,可是一般的朋友都是在宽带安装的时候,安装师傅帮忙设置的路由器,自己完全没有碰过路由器。
简单并不简单
2019/07/05
3.2K0
解密伪造钓鱼WiFi:安恒信息支招如何让WiFi使用更安全
央视3·15晚会再次关注手机应用安全问题,在晚会上曝光了免费WiFi的安全问题,并在现场给大家演示了利用伪造钓鱼WiFi技术窃取了台下观众的上网内容。坦白的说,很多手机用户也已经习惯“蹭网”,他们喜欢
安恒信息
2018/04/11
1.9K0
解密伪造钓鱼WiFi:安恒信息支招如何让WiFi使用更安全
解决Win10系统拨号上网无法开启移动热点wifi
前几天回成都了~回家的时候没有断开卧室的路由器,然后回来路由器就出问题了,此路由器为了访问国外网站,某宝买的个刷好了的Openwrt固件的,自己刷比较麻烦,但是就是wifi用着用着没了,检查了配置都没任何问题,今天又瞎折腾了下,网上自己搞了固件把系统都弄炸了,默认的Breed Web都进不去了!!应急为了给手机连下wifi,于是想到了Win10自带的移动热点功能。
Lcry
2022/11/29
6.1K0
解决Win10系统拨号上网无法开启移动热点wifi
WiFi密码查看技巧
由于现在智能机的普遍使用,想要连上网而到处搜wifi的人也跟着庞大了起来,但是很多wifi都设置了密码,想要破也不简单。于是为了冒个存在感,360推出了一款能提供免费wifi的软件,它能使你连上已被分
HACK学习
2019/08/07
2.8K0
WiFi密码查看技巧
【已解决】电脑连上网线但无法上网
网线在A电脑上可以正常,在B电脑上无法上网,且B电脑可以正常用无线上网,判断为B电脑网络设置的问题。如果为本案例类似情形,此解决方案会有帮助。
未名编程
2024/10/12
8080
【已解决】电脑连上网线但无法上网
由HTTPS抓包引发的一系列思考
在渗透测试过程中,必不可少的操作就是使用BurpSuite、Fildder等抓包工具对应用程序的数据包进行拦截、观察和篡改。那么问题来了——对于使用HTTPS协议的站点,在BurpSuite中拦截到的数据包为何也是“明文传输”?如下图所示。
FB客服
2019/12/30
1.9K0
linux树莓派连接wifi密码,树莓派 连接wifi与路由器ip绑定
1.JuiceSSH 橘子ssh软件 手机连上路由器 就可以控制局域网内的树莓派
全栈程序员站长
2022/08/24
7.2K0
linux树莓派连接wifi密码,树莓派 连接wifi与路由器ip绑定
前端-移动端调试痛点?——送你五款前端开发利器
之所以写这个总结,还要从上周的一次移动端项目的 debug 说起。那天,测试小姐姐拿着自己的 iphone6s 过来找我,说页面打不开。我想:这怎么可能,我手机里挺好的呀,Chrome调试工具也没报错呀!就把她手机拿过来看了看,发现一进去还真就是一片空白。WTF(手动黑人问号)!!!那问题就来了,开发环境下没报错,可真机又出现了意料之外的情况,而且没法像 PC端 那样祭出 F12 大法,怎么定位问题并解决呢?最后凭借着我(谷歌)的聪明才智,找到了媲美 PC端 调试体验的方式。在此总结一波,献给各位被移动端真机调试折磨,而又无从下手的前端er们,话休烦絮,直接奉上:
grain先森
2019/03/29
1.5K0
前端-移动端调试痛点?——送你五款前端开发利器
为什么有些网站手机能打开,但是电脑却不行?
最近有人后台留言问我说,他手机是用WiFi上网的,和电脑用的是同一网络,手机用的是本地浏览器,可以正常访问网页,但是电脑上却没法打开同一网页。听到这儿,就觉得十有八九就是DNS的问题,具体排查和解决方案如下,亲测有效。
半夜喝可乐
2021/08/23
30K0
路由器wds桥接方法-解决开发板、windows、ubuntu互ping问题
很多学习嵌入式Linux的同学一定会遇到一个问题:就是开发板、windows、ubuntu互相ping通怎么设置。我也不例外,即使我已经搭建过很多次这种环境,但是这一次我被折磨的有点崩溃了(开发板直连PC有限网卡,PC通过wifi上网),我搭建好之后,第二天又不行了,然后第二天又费了大量时间搞了一遍、第三天又不行了!
哆哆jarvis
2023/02/26
2.1K0
路由器wds桥接方法-解决开发板、windows、ubuntu互ping问题
电脑开WIFI、Win10 宽带拨号后无法设置移动热点
众所周知的,Win10 系统是可以用自带的网络开放热点给手机使用的,可以完全不借助任何第三方软件,比如在校园网环境使用的360共享wifi大师、电脑管家自带的wifi共享软件、猎豹wifi共享等等软件,由于校园网限制一人一号,不允许多帐号,所以触发了这些软件的发展市场,我也不例外,在学校就喜欢使用共享,一个寝室一个wifi即可搞定,但是!问题发生了,回到家里,直接使用宽带拨号后,去开启热点后提示:我们无法设置移动热点,因为你的电脑未建立以太网、Wi-Fi或者手机网络数据连接,截图如下:
Lcry
2022/11/29
2.4K0
电脑开WIFI、Win10 宽带拨号后无法设置移动热点
电脑硬件问题解决案例
本文记录了本人遇到的几个电脑硬件问题,以及尝试解决的过程。最终问题都算是解决了,不过也都算是瞎猫碰到死耗子吧,就当作给大家提供点思路吧。抛砖引玉,希望大家也能分享一些自己的案例。
独立观察员
2023/09/02
3310
电脑硬件问题解决案例
Pico Neo 2✨五、实现Pico到电脑的投屏
该WIFI必须和电脑处于相同的网络环境。就是说都是一根网线分享出来的网络,不管分出来的是以太网网线,还是路由器WIFI。
星河造梦坊官方
2024/08/15
5990
Pico Neo 2✨五、实现Pico到电脑的投屏
绕过WiFi验证:四招教你免费使用WiFi
如今越来越多的商场、咖啡店、饭店等公共场所都提供了开放的WiFi网络。不过有时即便我们的设备连上了WiFi,当随便打开一个网页就会立即弹出身份验证页面……是不是很郁闷?藉此新春佳节,小编将向大家分享几种绕过常见WiFi身份验证的方法,祝各位过个开心年。 仅供娱乐,请各位遵纪守法,别被老板暴打^_^ 需要身份认证的WiFi 这是一种开放的WiFi网络。在真正使用该网络之前,当访问任意网页时,通常你会遇到一个强制的身份认证的页面——只有在你输入了正确的用户名和密码之后才能开始使用该网络。 在我们的日常生
FB客服
2018/02/05
12.6K0
绕过WiFi验证:四招教你免费使用WiFi
计算机插了网线缺连不了网络,网线连不上网怎么回事_为什么网线插电脑上不了网-win7之家…
当我们在使用有线网络的时候,都需要在电脑中插入网线才可以,但是有不少用户却遇到网线连不上网的情况,为什么网线插电脑上不了网呢?导致这样问题的原因有很多,为了帮助到大家,现在给大家讲解一下网线连不上网的几种解决方法,一起来看看吧。
全栈程序员站长
2022/09/13
23.6K0
WIFI干扰器制作
WIFI干扰器制作 emmmm 不能瞎玩啊 被隔壁邻居举报了我不负责的 Esp8266的工作原理 Esp8266的工作原理,知乎有位大佬的回答: 解析一键配置,其大体工作原理如下: 设备进入初始化状态,开始收听附近的 WiFi 数据包。 手机/平板设置 WiFi 名字和密码后,发送 UDP 广播包。 设备通过 UDP 包(长度)获取配置信息,切换网络模式,连接上家里 WiFi,配置完成。 Broadlink最新的插座SP2 和RM2,e-Air等用的是Marvell E
安恒网络空间安全讲武堂
2018/02/06
12.4K1
WIFI干扰器制作
推荐阅读
相关推荐
Windows 7笔记本创建wifi热点供手机上网教程
更多 >
LV.1
这个人很懒,什么都没有留下~
目录
  • 杨老师上篇文章《MySQL时间分区的实现》介绍了时间类分区的实现方法,这篇是上篇的一个延伸,介绍基于此类分区的相关SQL编写注意事项。
    • 此表包含2020年一整年的数据,大概100W条,此处省略造数据过程。
    • 分别执行下面几条SQL:
    • 所以切记使用MySQL分区裁剪技术规定的分区函数来建立分区表,这样写SQL就会相对随意些。如果由于历史原因,分区表没有使用以上规定的分区函数,可以有以下两项可能的优化策略:
  • (2) 如果分区表使用的分区函数未满足MySQL分区裁剪技术的规则,该如何优化此类SQL语句?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档