当前位置:网站首页>MySQL 分区表介绍与测试
MySQL 分区表介绍与测试
2022-06-12 12:21:00 【Thai_】
一、基本介绍:
分区表是一个独立的逻辑表,底层由多个物理的文件组成,分区对于 SQL 层来说是透明的;
下图可以看出,表 em_elec_meter_data 的多个分区是使用了 # 进行标识。

分区表的使用场景:
- 表非常大以至于无法全部都放在内存中,或者热点数据只有在表的最后部分,其他都是历史数据。
- 分区表的数据作用在不同的设备上,高效地利用多个硬件设备;例如有 1TB 的数据,服务器的硬盘容量只有 500 GB,那么可以使用其他设备平摊未能放下的数据。
- 需要独立备份和恢复分区,这在非常大数据集的场景下效果非常好。
分区表的限制:
- 一个表最多只能有 1024 个分区。
- MySQL 5.1 中,分区表表达式必须是整数,或者返回整数表达式。在 MySQL 5.5 中,某些场景中可以直接使用列来进行分区。
- 如果分区字段中有主键或者唯一索引的列,那么所有主键列和唯一索引列都必须组合成一个主键;原因是防止同一个主键一个在 p0 区,一个在 p1 区。
- 分区表中无法使用外键约束(现在也没人使用外键,都是程序保证约束)。
- 在 MySQL 8 中不支持 myIsam 存储引擎使用分区表。
分区表的类型:
范围(range)分区,例如某年某月、不同省份的区域范围(常用)
注:每个分区都是按顺序进行定义,从最低到最高,例如以下的 2023 不能在 2022 的前面,这是 PARTITION BY RANGE 语法的要求
# 按照范围分区的表 create table `range_partition1` ( `id` bigint not null auto_increment, `date_time` datetime not null, `range_name` varchar(50) default null, primary key (`id`, `date_time`) ) ENGINE = InnoDB default CHARSET = utf8mb4 collate = utf8mb4_0900_ai_ci partition by range(year(date_time)) ( -- 必须按照顺序定义,否则报错 partition p0 values less than (2022), partition p1 values less than (2023) )哈希(hash)分区,将数据均匀的分布到预先定义的各个分区中,使用
partition by hash(expr)指定为 hash 分区,需要注意expr必须返回整数或者指定的列为 MySQL 的整型。CREATE TABLE `hash_partition` ( `id` bigint NOT NULL AUTO_INCREMENT, `date_time` datetime NOT NULL, `range_name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`,`date_time`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci partition by hash(id) partitions 10;partitions 10的意思为表要被切分成 10 个分区
键值(key)分区,KEY分区和HASH分区相似,不同之处在于 HASH 分区使用用户定义的函数进行分区,KEY 分区使用数据库提供的函数进行分区。
CREATE TABLE `key_partition` ( `id` bigint NOT NULL AUTO_INCREMENT, `date_time` datetime NOT NULL, `range_name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`,`date_time`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci partition by linear key(id) partitions 10;列表(list)分区,根据给定的 list 进行分区;以下例子为按照月份进行春夏秋冬四季的分区
CREATE TABLE `list_partition` ( `id` bigint NOT NULL AUTO_INCREMENT, `date_time` datetime NOT NULL, `range_name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`,`date_time`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci partition by list(month(date_time)) ( partition spring values in (3, 4, 5), partition summer values in (6, 7, 8), partition autumn values in (9, 10, 11), partition winter values in (12, 1, 2) )
二、分区表的优缺点
优点:
- 提升查询性能,对于分区表的查询操作,如果查询条件中包含分区键,则这个查询操作就只会被下推到符合条件的分区内进行,无关分区将自动过滤掉。
- 对业务透明,将表从一个非分区表转换为分区表,业务端无需做任何改造。在开发看来,仍然是同一张表。
- 维护方便,在对单个分区进行删除、迁移和维护时,不会影响到其它分区。
- DML 操作加锁仅影响操作的分区,不会影响未访问分区。
缺点:
- DDL 操作需要锁定所有分区,导致所有分区上操作都被阻塞。
- 当表数据量较小时,分区表和非分区表性能相近,分区表效果有限。
- 当表数据量较大时,对分区表进行 DDL 或其他运维操作难度大风险高。
- 分区表使用较少,存在未知风险多,BUG多,BUG多,BUG多,MySQL社区版本免费,横向扩展成本低,分库分表实现简单且中间件完善。
- 当单台服务器性能无法满足时,对分区表进行分拆的成本较高,而分库分表能很容易实现横向分拆。
- 当分区表操作不当导致访问所有分区时,会导致严重的性能问题,而分库分表操作不当仅影响访问的表。
- 使用分库分表可以有效运维降低运维操作影响,对1亿数据量表做 DDL 操作需要谨慎评估,而对 10 万数据量表做 DDL 操作可以默认其很快完成。
- 使用分库分表可以有效减小宕机或其他故障影响,将数据分库分表到10套群集上,一套群集发生故障仅影响业务的一成。
三、测试:
新建表 em_elec_meter_data,按月份从 2019 年到 2023 年对表进行分区划分。
CREATE TABLE `em_elec_meter_data` (
`id` bigint NOT NULL COMMENT '表主键',
`date_time` datetime NOT NULL COMMENT '时间。',
`create_time` datetime DEFAULT NULL COMMENT '改记录生成的时间',
PRIMARY KEY (`id`,`date_time`),
UNIQUE KEY `IDX_MIDDATE` (`meter_id`,`date_time`),
KEY `IDX_DATETIME` (`date_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=''
/*!50100 PARTITION BY RANGE (to_days(`date_time`)) (PARTITION md201901 VALUES LESS THAN (737456) ENGINE = InnoDB, 略..... PARTITION md202312 VALUES LESS THAN (739251) ENGINE = InnoDB) */
向表插入数据, em_elec_meter_data 有大概 7 千万条数据,下面演示使用分区与不使用分区的差别

首先看不使用分区,执行以下 SQL,实测耗时 1 min 7 s
select
sql_no_cache /* 为了更真实,不使用缓存 */
*
from
test.em_elec_meter_data
where
dya = 10086

查看它的执行计划,需要查找所有的分区,大概扫描 66184007 行记录才找到 dya = 10086 这条记录

添加分区字段过滤,执行以下 SQL,实测耗时 1ms,性能提高约 67000 倍
select
sql_no_cache /* 为了更真实,不使用缓存 */
*
from
test.em_elec_meter_data
where
dya = 10086
and date_time = '2019-01-01 13:56:59';

再看看执行计划,只需查找 md201901 这个分区,且用到了 date_time索引

参考:
高性能 MySQL
https://www.cnblogs.com/gaogao67/p/11013244.html?ivk_sa=1024320u
边栏推荐
- Elk construction guide
- Clone with cloneNode to solve the id problem / methods deep copy and shallow copy to modify the ID
- 22年gdcpc广东省赛记录
- [译] QUIC Wire Layout Specification - Packet Types and Formats | QUIC协议标准中文翻译(2) 包类型和格式
- What can LDAP and SSO integration achieve?
- this的指向
- A short guide to SSH port forwarding
- NDT registration principle
- What is modularity? Benefits of modularity
- QML first day
猜你喜欢

你不会只会用console.log()吧?

Principle of master-slave replication of redis

mysql复习

In navigation, the solution of adding borders to affect the layout

Find the median of two ordered arrays (leetcode 4)

Asynchronous path processing

轻量化---Project

Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference

Kdd2022 | edge information enhancement graph transformer

Dom and BOM in JS
随机推荐
Invalid date of moment conversion timestamp
TRON-api-波场转账查询接口-PHP版本-基于ThinkPHP5封装-附带接口文档-20220602版本-接口部署好适用于任何开发语言
The difference between bind, call and apply, and the encapsulation of bind()
Easy to use assistant tools and websites
BAT面试&高级进阶,文末领取面试资料
Common debugging tools and commands for ROS
无重复字符的最长字符串(LeetCode 3)
LeetCode 890. Find and replace mode (analog + double hash table)
A short guide to SSH port forwarding
Autolock solves the problem of forgetting to unlock after locking
Bat interview & advanced, get interview materials at the end of the text
Vim,Gcc,Gdb
In navigation, the solution of adding borders to affect the layout
Kdd2022 | edge information enhancement graph transformer
关于报文
for in 与Object.keys()的区别
安装canvas遇到的问题和运行项目遇到的报错
Dom+js+ carousel map + no time
Cocktail sort
Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference