MySQL 实战 45 讲
林晓斌
网名丁奇,前腾讯云数据库负责人
224874 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
实践篇 (37讲)
特别放送 (1讲)
结课测试 (1讲)
MySQL 实战 45 讲
15
15
1.0x
00:00/00:00
登录|注册

43 | 要不要使用分区表?

用MyISAM表锁验证
分区表的加锁范围
普通表的加锁范围
分区表的MDL锁
MyISAM分区表的例子
间隙锁示例
分区表的注意事项
分区表的问题
分区表的优势
本地分区策略
通用分区策略
Server层行为
引擎层行为
支持通配符的权限赋值
总结
分区表的应用场景
分区策略
分区表是什么?
上期问题时间
分区表的使用行为

该思维导图由 AI 生成,仅供参考

我经常被问到这样一个问题:分区表有什么问题,为什么公司规范不让使用分区表呢?今天,我们就来聊聊分区表的使用行为,然后再一起回答这个问题。

分区表是什么?

为了说明分区表的组织形式,我先创建一个表 t:
CREATE TABLE `t` (
`ftime` datetime NOT NULL,
`c` int(11) DEFAULT NULL,
KEY (`ftime`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
PARTITION BY RANGE (YEAR(ftime))
(PARTITION p_2017 VALUES LESS THAN (2017) ENGINE = InnoDB,
PARTITION p_2018 VALUES LESS THAN (2018) ENGINE = InnoDB,
PARTITION p_2019 VALUES LESS THAN (2019) ENGINE = InnoDB,
PARTITION p_others VALUES LESS THAN MAXVALUE ENGINE = InnoDB);
insert into t values('2017-4-1',1),('2018-4-1',1);
图 1 表 t 的磁盘文件
我在表 t 中初始化插入了两行记录,按照定义的分区规则,这两行记录分别落在 p_2018 和 p_2019 这两个分区上。
可以看到,这个表包含了一个.frm 文件和 4 个.ibd 文件,每个分区对应一个.ibd 文件。也就是说:
对于引擎层来说,这是 4 个表;
对于 Server 层来说,这是 1 个表。
你可能会觉得这两句都是废话。其实不然,这两句话非常重要,可以帮我们理解分区表的执行逻辑。

分区表的引擎层行为

我先给你举个在分区表加间隙锁的例子,目的是说明对于 InnoDB 来说,这是 4 个表。
图 2 分区表间隙锁示例
这里顺便复习一下,我在第 21 篇文章和你介绍的间隙锁加锁规则。
我们初始化表 t 的时候,只插入了两行数据, ftime 的值分别是,'2017-4-1' 和'2018-4-1' 。session A 的 select 语句对索引 ftime 上这两个记录之间的间隙加了锁。如果是一个普通表的话,那么 T1 时刻,在表 t 的 ftime 索引上,间隙和加锁状态应该是图 3 这样的。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

分区表是数据库中的一种组织形式,通过将数据分散存储在不同的分区中,可以提高查询性能和管理大型数据表。文章首先介绍了分区表的引擎层行为,包括InnoDB和MyISAM引擎对分区表的处理方式。其次,文章讨论了手动分表和分区表的区别,指出从引擎层看,这两种方式并没有实质的差别。然后,文章详细介绍了分区策略的重要性,以及MySQL对分区表的支持情况和性能问题。最后,文章总结了分区表在server层的行为,包括对MDL锁的影响和查询语句中的where条件对分区访问的影响。总的来说,分区表适合用于管理大型数据表和提高查询性能,但在使用过程中需要注意分区策略和对MDL锁的影响。 分区表的应用场景包括对业务透明、简洁的业务代码和方便的历史数据清理。然而,实际使用时需要注意访问所有分区的性能问题和共用MDL锁的影响。此外,文章还提到了分区表的其他问题,如查询性能慢和数据量问题。最后,留下了一个思考题,引发读者对分区表的主键定义进行思考。 总的来说,本文深入探讨了分区表在数据库中的应用和性能问题,为读者提供了全面的了解和思考。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《MySQL 实战 45 讲》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(39)

  • 最新
  • 精选
  • 夹心面包
    置顶
    我说下我的感想 1 经典的利用分区表的场景 1 zabbix历史数据表的改造,利用存储过程创建和改造 2 后台数据的分析汇总,比如日志数据,便于清理 这两种场景我们都在执行,我们对于分区表在业务采用的是hash 用户ID方式,不过大规模应用分区表的公司我还没遇到过 2 分区表需要注意的几点 总结下 1 由于分区表都很大,DDL耗时是非常严重的,必须考虑这个问题 2 分区表不能建立太多的分区,我曾被分享一个因为分区表分区过多导致的主从延迟问题 3 分区表的规则和分区需要预先设置好,否则后来进行修改也很麻烦

    作者回复: 👍 非常好

    2019-02-20
    3
    72
  • aliang
    老师,mysql还有一个参数是innodb_open_files,资料上说作用是限制Innodb能打开的表的数量。它和open_files_limit之间有什么关系吗?

    作者回复: 好问题。 在InnoDB引擎打开文件超过 innodb_open_files这个值的时候,就会关掉一些之前打开的文件。 其实我们文章中 ,InnoDB分区表使用了本地分区策略以后,即使分区个数大于open_files_limit ,打开InnoDB分区表也不会报“打开文件过多”这个错误,就是innodb_open_files这个参数发挥的作用。

    2019-02-21
    4
    70
  • 万勇
    老师,请问add column after column_name跟add column不指定位置,这两种性能上有区别吗?我们在add column 指定after column_name的情况很多。

    作者回复: 仅仅看性能,是没什么差别的 但是建议尽量不要加after column_name, 也就是说尽量加到最后一列。 因为其实没差别,但是加在最后有以下两个好处: 1. 开始有一些分支支持快速加列,就是说如果你加在最后一列,是瞬间就能完成,而加了after column_name,就用不上这些优化(以后潜在的好处) 2. 我们在前面的文章有提到过,如果怕对线上业务造成影响,有时候是通过“先做备库、切换、再做备库”这种方式来执行ddl的,那么使用after column_name的时候用不上这种方式。 实际上列的数据是不应该有影响的,还是要形成好习惯😆

    2019-02-21
    6
    38
  • 郭江伟
    此时主键包含自增列+分区键,原因为对innodb来说分区等于单独的表,自增字段每个分区可以插入相同的值,如果主键只有自增列无法完全保证唯一性。 测试表如下: mysql> show create table t\G Table: t Create Table: CREATE TABLE `t` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ftime` datetime NOT NULL, `c` int(11) DEFAULT NULL, PRIMARY KEY (`id`,`ftime`), KEY `ftime` (`ftime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 /*!50100 PARTITION BY RANGE (YEAR(ftime)) (PARTITION p_2017 VALUES LESS THAN (2017) ENGINE = InnoDB, PARTITION p_2018 VALUES LESS THAN (2018) ENGINE = InnoDB, PARTITION p_2019 VALUES LESS THAN (2019) ENGINE = InnoDB, PARTITION p_others VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */ 1 row in set (0.00 sec) mysql> insert into t values(1,'2017-4-1',1),(1,'2018-4-1',1); Query OK, 2 rows affected (0.02 sec) mysql> select * from t; +----+---------------------+------+ | id | ftime | c | +----+---------------------+------+ | 1 | 2017-04-01 00:00:00 | 1 | | 1 | 2018-04-01 00:00:00 | 1 | +----+---------------------+------+ 2 rows in set (0.00 sec) mysql> insert into t values(null,'2017-5-1',1),(null,'2018-5-1',1); Query OK, 2 rows affected (0.02 sec) mysql> select * from t; +----+---------------------+------+ | id | ftime | c | +----+---------------------+------+ | 1 | 2017-04-01 00:00:00 | 1 | | 2 | 2017-05-01 00:00:00 | 1 | | 1 | 2018-04-01 00:00:00 | 1 | | 3 | 2018-05-01 00:00:00 | 1 | +----+---------------------+------+ 4 rows in set (0.00 sec)

    作者回复: 👍

    2019-02-20
    6
    29
  • wljs
    老师我想问个问题 我们公司一个订单表有110个字段 想拆分成两个表 第一个表放经常查的字段 第二个表放不常查的 现在程序端不想改sql,数据库端来实现 当查询字段中 第一个表不存在 就去关联第二个表查出数据 db能实现不

    作者回复: 用view可能可以实现部分你的需求,但是强烈不建议这么做。 业务不想修改,就好好跟他们说,毕竟这样分(常查和不常查的垂直拆分)是合理的,对读写性能都有明显的提升的。

    2019-02-20
    4
    22
  • 老师确认下,5.7.9之后的innodb分区表,是访问第一个表时不会去打开所有的分区表了吗?

    作者回复: 第一次访问的时候,要打开所有分区的

    2019-02-25
    3
    21
  • 权恒星
    这个只适合单机吧?集群没法即使用innodb引擎,又支持分区表吧,只能使用中间件了。之前调研了一下,官方只有ndb cluster才支持分区表?

    作者回复: 对这篇文章讲的是单机上的单表多分区

    2019-02-20
    5
    12
  • 千木
    老师您好,你在文章里面有说通用分区规则会打开所有引擎文件导致不可用,而本地分区规则应该是只打开单个引擎文件,那你不建议创建太多分区的原因是什么呢?如果是本地分区规则,照例说是不会影响的吧,叨扰了

    作者回复: “本地分区规则应该是只打开单个引擎文件”,并不是哈,我在文章末尾说了,也会打开所有文件的,只是说本地分区规则有优化,比如如果文件数过多,就会淘汰之前打开的文件句柄(暂时关掉)。 所以分区太多,还是会有影响的

    2019-02-20
    2
    11
  • 怀刚
    请教下采用”先做备库、切换、再做备库”DDL方式不支持AFTER COLUMN是因为BINLOG原因吗? 以上DDL方式会存在影响“有损”的吧?“无损”有哪些方案呢?如果备库承载读请求但又不能接受“长时间”延时

    作者回复: 1. 对,binlog对原因 2. 如果延迟算损失,确实是有损的。备库上的读流量要先切换到主库(也就是为什么需要在低峰期做做个操作)

    2019-03-09
    8
  • zc
    alter table t drop partition 不加元数据锁吗?

    作者回复: 要加 不过因为时间很短,可以认为是安全操作

    2020-02-10
    7
收起评论
显示
设置
留言
39
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部