MySQL分区表简介
wptr33 2024-11-24 22:27 22 浏览
一、背景
我们的业务只存近一段时间的数据,因此有大量表需要清理历史数据,目前使用的delete清理数据,存在以下问题。为避免同时支持大量delete,我们的清理任务只在低峰期串行执行,导致任务过多时需要排队,甚至失败的情况;数据清理使用delete语句,表数据量较大时,对数据库造成很大压力;即使我们删除了旧数据,已删除的数据仍占据存储空间,底层数据文件并没有立刻变小,以至于形成数据空洞。
查看MySQL官方文档时,发现了分区表,因此基于官方文档总结一下。
二、什么是分区表?
MySQL逻辑上为一个表,物理上存储在多个文件中,这是 MySQL 支持的功能(5.1 开始), 8.0 版本只 InnoDB 和 NDB 支持分区表。
三、分区表有啥优缺点?
优点:
- 和单个磁盘或文件系统分区相比,可以存储更多的数据。
- 优化查询:
- where 子句中包含分区条件时,可以直接扫描必要的分区。
- 涉及聚合函数的查询时,可以很容易地在每个分区上并行处理,最终只需汇总得到结果。
- 对于已经过期或者不需要保存的数据,可以通过删除与这些数据有关的分区来快速删除数据。
- 跨多个磁盘来分散数据查询,以获得更大的查询吞吐量。
缺点:
- 新建、删除分区操作的时候,会获取表的MDL锁,这是一把全局锁,可能会对业务产生慢查的影响;
- 分区表在执行alter语句时,比如增加、删除分区,更容易出现MDL锁冲突,引起慢查等情况;
- InnoDB分区表不支持外键
四、分区类型
4.1 Range 分区
根据分区表键值的范围把数据存储到表的不同分区中,适用于以时间或日期作为分区类型,方便数据清理。
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL )
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN (21)
);
-- 使用函数将日期转换
CREATE TABLE employees_1 (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL )
PARTITION BY RANGE (year(hired)) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN (21) );
-- 使用date 或 datetime 例作为分区例时 可使用 RANGE COLUMNS 对表进行分区
CREATE TABLE employees_2 (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL )
PARTITION BY RANGE COLUMNS (hired) (
PARTITION p0 VALUES LESS THAN ('1970-01-01'),
PARTITION p1 VALUES LESS THAN ('1971-01-01'),
PARTITION p2 VALUES LESS THAN ('1972-01-01'),
PARTITION p3 VALUES LESS THAN ('1973-01-01')
);
小提示:
1.当插入数据分区不存在时会报错:Table has no partition for value xxx;
2.Range类型分区字段必须是数值,时间类型可用函数转换为数值;
3.分区字段列值可以为null,所有为null的数据将存在最小的分区中;
4.2 List分区
按分区键取值的列表进行分区,每一行数据须找到对应的分区列表,否则数据插入失败
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT )
PARTITION BY LIST(store_id) (
PARTITION pNorth VALUES IN (3,5,6,9,17),
PARTITION pEast VALUES IN (1,2,10,11,19,20),
PARTITION pWest VALUES IN (4,12,13,14,18),
PARTITION pCentral VALUES IN (7,8,15,16)
);
小提示:
- List分区表不存在 MAXVALUE 之类的,所以在设计时一定要全面评估,否则分区不存在时写入会报错;
- 可以显示指定一个null分区,eg: pxx values in (null);
- 如果没有指定null分区时,分区字段值为null会报错:Table has no partition for value NULL;
4.3 Hash分区
根据指定分区表达式的整数值以及分区数进行数据划分(mod函数)
CREATE TABLE employees_hash (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT, store_id INT )
PARTITION BY HASH(store_id) PARTITIONS 4;
小提示:
- 当分区表达式输出为null时,被当做0处理;
4.4 Key分区
按键分区类似于按哈希分区,只是哈希分区使用用户定义的表达式,用于键分区的哈希函数由 MySQL 服务器提供。NDB 集群为此使用 MD5() ; 对于使用其他存储引擎的表,服务器使用自己的内部哈希函数。
CREATE TABLE k1 (
id INT NOT NULL,
name VARCHAR(20),
UNIQUE KEY (id) )
PARTITION BY KEY() PARTITIONS 2;
小提示:
- 分区字段不填写时,可以不填写分区字段,优先使用主键作为分区字段,其次是唯一键;没有主键或唯一键时,分区字段必填
- 分区字段可以是非整数或null值;
- 当分区表达式输出为null时,被当做0处理;
4.3 子分区
子分区(subpartitioning)也称为复合分区(composite partitioning) ,是已分区表中每个分区的进一步划分
CREATE TABLE ts (
id INT,
purchased DATE)
PARTITION BY RANGE( YEAR(purchased) )
SUBPARTITION BY HASH( TO_DAYS(purchased) )
SUBPARTITIONS 2 (
PARTITION p0 VALUES LESS THAN (1990),
PARTITION p1 VALUES LESS THAN (2000),
PARTITION p2 VALUES LESS THAN MAXVALUE
);
小提示:
- 每个分区必须具有相同数量的子分区;
五、分区管理
5.1 Range 和 List
-- 增加分区
alter table employees_list add partition (partition pxx values in (null)); ALTER TABLE tt ADD PARTITION (PARTITION p2 VALUES IN (7, 14, 21));
-- 删除分区
ALTER TABLE employees_list DROP PARTITION pxx;
-- 将一个分区分为多个分区
ALTER TABLE employees_3 REORGANIZE PARTITION employees_list INTO (
PARTITION n0 VALUES LESS THAN (1970),
PARTITION n1 VALUES LESS THAN (1980) );
-- 清空分区
ALTER TABLE employees_3 TRUNCATE PARTITION pxx;
5.2 Hash 和 Key分区
-- 缩减n个分区
ALTER TABLE employees_hash COALESCE PARTITION 4;
-- 增加n个分区
ALTER TABLE employees_hash ADD PARTITION PARTITIONS 6;
小提示:
- 使用COALESCE 减少分区数时,不能减少至0;
六、指定分区查询
-- 可以指定分区号或以分区字段作为条件
select * from employees_hired PARTITION (p2021)
where store_id = 551 and hired >= '2020-12-31' and hired <= '2021-01-01'
七、分区表注意事项
- PRIMARY KEY、UNIQUE KEY 必须包含分区字段;
- 分区表达式支持函数,但不是所有函数都支持,存储过程、存储函数、可加载函数和插件都不支持,算术运算符支持 +、- 、* 、div,不支持"/",位运算也不支持;
- MySQL 8.0 仅InnoDB和NDB支持分区表,其他engine不支持;
- range 分区中,null 值会被当作最小值来处理;
- list 分区中,null 值必须出现在枚举列表中,否则不被接受;
- hash/key 分区中,null 值会被当作零值来处理。
相关推荐
- 一篇文章带你了解PHP的学习使用(php的教程)
-
ThinkPHP5实战...
- 在memcached管理php的session(memcached libevent)
-
PHP的session(会话管理)一般是以文件形式进行,而在多个Web服务器之间进行session管理时memecached会比文件管理方式更加方便。在这里介绍如何使用memcached管理PHP的s...
- php传值和传引用的区别(php 传值和传引用)
-
php传值:在函数范围内,改变变量值得大小,都不会影响到函数外边的变量值。PHP传引用:在函数范围内,对值的任何改变,在函数外部也有所体现,因为传引用传的是内存地址。传值:和copy是一样的。【打个比...
- PHP 常量详解教程(php常量和变量)
-
常量类似变量,但是常量一旦被定义就无法更改或撤销定义。PHP常量常量是单个值的标识符(名称)。在脚本中无法改变该值。有效的常量名以字符或下划线开头(常量名称前面没有$符号)。注释:与变量不同,常...
- php自学零基础入门小知识(php新手入门教程)
-
我们就把PHP入门当成一个苹果吧!一口一口的吃掉他!不啰嗦了!开始了1、嵌入方法:类似ASP的<%,PHP可以是<?php或者是<?,结束符号是?>,当然您也可以自己指定。2、...
- PHP 语法详解(php语法大全)
-
PHP脚本在服务器上执行,然后向浏览器发送回纯HTML结果。基础PHP语法PHP脚本可放置于文档中的任何位置。PHP脚本以<?php开头,以?>结尾:<?php...
- PHP笔记(一)PHP基础知识(php必背知识点)
-
创建PHP程序PHP代码框架<?php>2.文件命名规则...
- PHP 8新特性之Attributes(注解),你掌握了吗?
-
PHP8的Alpha版本,过几天就要发布了,其中包含了不少的新特性,当然我自己认为最重要的还是JIT,这个我从2013年开始参与,中间挫折无数,失败无数后,终于要发布的东东。不过,今天呢,我不打算谈J...
- PHP基本语法之标记与注释(php注释规范)
-
1、标记由于PHP是嵌入式脚本语言,它在实际开发中经常会与HTML内容混在一起,所以为了区分HTML与PHP代码,需要使用标记对PHP代码进行标识。如:<html>...
- php注解(PHP注解 性能)
-
目标了解和使用php注解,如果你已经掌握其他一种具有注解的语言,例如:java、python等,你在本文中只需要了解点语法就行。示例php8以前的版本,注解写在注释里,如果你掌握其他语言的注解,你是不...
- 数据丢失?别慌!MySQL备份恢复攻略
-
想象一下,某个晴朗的午后,你正享受着咖啡,突然接到紧急电话:你的网站或APP彻底挂了!系统崩溃,界面全白。虽然心头一紧,但你或许还能安慰自己:系统崩溃只是暂停服务,数据还在,修复修复就好了。然而,如果...
- MySQL 日志:undo log、redo log、binlog
-
今天来和大家分享MySQL的三个日志文件,可以说MySQL的多数特性都是围绕日志文件实现,而其中最重要的有以下三种:...
- MySQL三大日志:binlog、redolog、undolog全解析
-
binlog概述在MySQL数据库中,binlog可是个相当重要的存在,它的全称为binarylog,也就是二进制日志。它就像是数据库的“记忆本”,记录了所有的DDL(数据定义语言)和...
- 1、MySQL数据库介绍(mysql数据库简单介绍)
-
1.1数据库的核心定义数据库的本质数据库乃存储数据对象之容器,涵盖如下关键组件:表(Table)...
- MySQL 日志双雄:实时监控与历史归档实战优化
-
MySQL日志双雄:实时监控+历史归档实战用这招让你家日志系统再也不卡不爆炸MySQL十亿级日志处理:从洪峰到归档全攻略手把手教你用MySQL搞定ELK级日志监控在微服务架构大行其道的今天,日志系统早...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)