当前位置:   article > 正文

MySQL分区表实践及性能优化技巧 - RDS下的分区表实践

mysql5.6 分区表 性能

186b80d70295b991347005638667d1e3.png

实践背景

项目中有的表空间太大,且行数太多,故决定对一些表进行分库分表。再研究选型方案的时候发现常用的一些分库分表的解决方案对业务代码修改较多,故决定采用MySQL的分区方案。

其实在我个人看来,分区表就是MySQL帮我们实现了底层的分库分表,不需要涉及业务代码的修改,不需要关注分布式事务。因为就访问数据库而言,逻辑上还是只有一个表,但是实际上确有多个物理分区对象组成,会根据具体的分区规则查询具体的分区。

介绍一下这次实践的表,表空间大小172G,1亿2千万条记录。

数据库版本:RDS MySQL 5.6

工具:阿里云DTS

一、为什么分区?

优点:

  • 对已过期或者不需要保存的数据,可以通过删除与这些数据有关的分区来快速删除数据,它的效率远比DELETE高
  • 在where子句中包含分区条件时,可以只扫描必要的一个或者多个分区来提高查询效率

例如下面语句:

SELECT * FROM t PARTITION(p0,p1)WHERE c <5 仅选择与WHERE条件匹配的分区p0和p1中的记录

  • 涉及聚合函数SUM()、COUNT()的查询时,会在每个分区上并行处理
  • 分区把原本一个表的数据存储在多个物理磁盘上,实现了更高的IOPS

缺点:

  • 无法使用外键,不支持全文索引(现在应该也没什么公司还在用外键吧)
  • 分区键设计不太灵活,如果不走分区键,很容易出现全表锁
  • 开发写一个SQL,不清楚mysql是怎么玩的

二、RANGE分区

目前MySQL支持范围分区(RANGE),列表分区(LIST),哈希分区(HASH)以及KEY分区四种。

本文是以范围分区(RANGE)对时间进行的分区的,故我就简单介绍一下RANGE分区。更多分区类型详见官方文档MySQL 5.6 分区类型

基于一个给定连续区间的列值,根据区间分配分区。最常见的是基于时间字段。其实基于分区的列最好是整型,如果日期型的可以使用函数转换为整型。MySQL 5.6支持的分区函数

本例中使用TO_DAYS函数

  1. CREATE TABLE members (
  2. id VARCHAR(25) NOT NULL,
  3. firstname VARCHAR(25) NOT NULL,
  4. lastname VARCHAR(25) NOT NULL,
  5. username VARCHAR(16) NOT NULL,
  6. email VARCHAR(35),
  7. joindate DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
  8. PRIMARY KEY (id,joindate) USING BTREE,
  9. KEY idx_joindate (joindate) USING BTREE
  10. )ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT
  11. PARTITION BY RANGE (TO_DAYS(joindate)) (
  12. PARTITION p0 VALUES LESS THAN (TO_DAYS('1960-01-01')),
  13. PARTITION p1 VALUES LESS THAN (TO_DAYS('1970-01-01')),
  14. PARTITION p2 VALUES LESS THAN (TO_DAYS('1980-01-01')),
  15. PARTITION p3 VALUES LESS THAN (TO_DAYS('1990-01-01')),
  16. PARTITION p4 VALUES LESS THAN MAXVALUE
  17. );

PS:像例子中的如果你有主键或唯一索引,你必须把你的分区键也加上,其中joindate就是分区键,要不创建会失败!

PS:像上面加了LESS THAN MAXVALUE,后面就不能新加分区了!!!

示例:

如下查询就会落在定义的p2分区内的索引上。故在查询的时候带上你的分区键就会走对应分区查询数据,如果你的条件跨越多个分区进行聚合函数SUM()、COUNT()的查询时,它会在每个分区上并行处理。如果没有带分区键查询就会全表查询。

explainpartitionsselect * from members WHERE joindate BETWEEN'1970-02-03'AND'1970-02-04';

7f85baa0f836b040f06812a876477a71.png

我在迁移完数据进行查询的时候发现一个特别有意思的现象,同一条SQL如果分区键的时间区间不一样,它会根据rows行数少的走不同的范围索引。至于它底层是怎么实现的我就没去研究了。

三、分区管理

简单介绍了下范围分区,接下来说一下对分区常用的一下操作。

分区管理包括对于分区的增加,删除,以及查询。更多详见官方文档MySQL 分区管理

1.增加分区

对于RANGE和LIST分区:

  1. alter table table_name add partition (partition p0 values ...(exp))
  2. #例
  3. ALTER TABLE members ADD PARTITION (TO_DAYS('2021-03-01'));

2.删除分区

删除了分区,同时也将删除该分区中的所有数据。如果删除了分区导致分区不能覆盖所有值,那么插入数据的时候会报错。

altertable table_name droppartition p0; 

3.查询有多少个分区

SELECT * FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 'members';

296dacc102f312f4c48673397e4693c1.png

四、数据迁移

前面说了那么多概念,我说一下本次把大表数据迁移到分区表的过程。

为什么会选择DTS呢?因为它可以不停机迁移数据,支持全量迁移和增量迁移,对原表影响不大。

迁移过程如下:

  1. 首先在RDS的同一个实例里面新建了一张同结构的分区表
  2. 使用DTS创建迁移任务,迁移时候不要选择结构钱谦益,只选择全量+增量迁移
  3. 然后还需要编辑下目标库表名,也就是做下映射从A->B的迁移
  4. 停掉写入数据的任务,当任务队列为空时,等待几分钟暂停并结束迁移任务
  5. 最后修改表名,完成数据迁移和切换(我在测试环境修改分区表名要一些时间,但RDS修改表名是秒改)

参考官方文档:MySQL 5.6 分区

以上纯属个人观点,如有不对欢迎指正。

作者:剧与
出自:开源中国
原文:MySQL--RDS下的分区表实践 - 剧与的个人空间 - OSCHINA

MySQL34道经典面试题:

这34道面试题非常之经典,非常之赞,很多学过的朋友都会推荐给小伙伴一起学习

a024b47bbff36d5586912f82681f5bb4.png

1451ea5c9917c0b0b8c41f88d92f6e76.png

有需要的小伙伴可以留言“MySQL面试题”看到后会逐一发送的


杜老师B站最新MySQL视频教程:

ba82b5981c507050b3621459bc8099f1.png

e9a903f1f7e9d176a282fff2c6656881.png

有需要的小伙伴可以留言“MySQL教程”看到后会逐一发送的

本教程经动力节点授权转载

推荐阅读:

java钢铁侠-马克51号:面试官:你简历中写用过docker,能说说容器和镜像的区别吗?​zhuanlan.zhihu.com
77003d5dc9570cc6c055d921ac9f1bdb.png
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/902333
推荐阅读
相关标签
  

闽ICP备14008679号