【业务功能篇44】Mysql 海量数据查询优化,进行分区操作

news2024/12/23 9:45:12

业务场景:当前有个发料表,随着业务数据量增多,达到了几千万级别水平,查询的效率就越来越低了,针对当前的架构情况,我们进行了分区的设置,通过对时间字段,按年月,一个月作为一个分区,这样查询效率会有一定程度的提升

业务上,会查询表中多个字段,比如条码,批次,时间。其中,作为时间字段来说,可能是种类比较少的,分区的个数不建议过多,那么我们最后就选择了按时间分区

  • 由于表是先创建的,后续进行分区的设计,所以就是要进行修改表
  • PARTITION by LIST COLUMNS (YEAR_MON)   按照时间列分区,这里采用按一个月为一个分区,进行划分,如果数据量越发增大,可能后续也需要将较远的历史数据分区切到一个外部表中
  • 假如一个月的数据量不多,结合实际业务场景,可能将多个月划分在一个分区中

分区表的操作sql 

 alter table `表名称` PARTITION by LIST COLUMNS (YEAR_MON)
 (
     PARTITION p1 VALUES IN ('2023-01'),
     PARTITION p2 VALUES IN ('2023-02'),
     PARTITION p3 VALUES IN ('2023-03'),
     ……
     PARTITION pN VALUES IN ('2023-07')
)


  • 下面介绍下分区整体的一些知识点 
  • 一个表最多只能有1024个分区(mysql5.6之后支持8192个分区)

分区类型

range,list,hash,key这四种分区中,分区的条件是:数据必须是整型,如果不是整型,那应该通过函数将其转化为整型(如:YEAR(),TO_DAYS(),MONTH()等函数)。

 range分区

  • 对于range分区的查询,优化器只能对YEAR(),TO_DAYS(),TO_SECONDS(),UNIX_TIMESTAMP()这类函数进行优化分区。
create table sales (
money int unsigned not null,
date datetime
) engine=innodb
partition by range (TO_DAYS(date)) (
partition p201001 values less than (TO_DAYS('2010-02-01')),
partition p201002 values less than (TO_DAYS('2010-03-01')),
partition p201003 values less than (TO_DAYS('2010-04-01'))
);

list分区

  • list分区,如果是插入多行数据时,有不符合分区规则情况下,myisam存储引擎会存放符合分区规则的,而innodb会把它看成一个事务,不会插入数据,会报错
create table t1(
a int,
b int
) engine=innodb
partition by list(b) (
partition p0 values in (1,3,5,7,9),
partition p1 values in (0,2,4,6,8)
);

hash分区

  • --- hash分区 是将数据均匀的分配到预先定义的各个分区中,保证各分区的数量大致都是一样的
  • --- 要使hash分区来分割一个表,要在create table 语句上添加“partition by hash(expr)”子句,其中expr是一个返回一个整数的表达式,它可以仅仅是字段类型为mysql整型的列名。
  • --- 此外用户很可能需要在后面再添加一个"partitions num"子句,其中num是一个非负整数,表示表将要分割成分区的数量,没有这个子句,默认是1
  • hash分区是取模算法:如b为2010-04-01时 mod(year('2010-04-01'), 4) = mod(2010, 4) = 2 因此记录会被放入分区p2中。
create table t2(

a int,

b datetime

) engine=innodb

partition by hash (year(b))

partitions 4;

另一种hash分区——linear hash(hash算法不同)

  • 这种分区算法的优点是:增加、删除、合并、和拆分分区将变得更加快捷,有利于含有处理大量数据的表。
  • 缺点是:与使用hash分区得到的数据分布相比,各个分区间数据的分布可能不大均匀。
  • 分区算法是:同样是2010-04-01
  • 1、取大于分区数量num=4的下一个2的幂值V,V = power(2, ceiling(log(2, NUM))) = 4;即log以2为底num的指数作为2的幂值。2^log(2, num)
  • 2、所在分区N = YEAR('2010-04-01') & (V - 1) = 2
create table t3(

a int,

b datetime

)engine=innodb

partition by linear hash (year(b))

partitions 4;

key分区


  • key分区和hash分区相似,不同之处在于hash分区使用用户定义的函数进行分区,key分区使用MySQL数据库提供的函数进行分区。对于NDB cluster引擎,MySQL数据库使用MD5函数分区,对于其他的数据库引擎,MySQL数据库使用其内部的哈希函数,这些函数基于与password()一样的运算法则
  • 在key分区中使用关键字linear和在hash分区中使用具有相同的效果,分区标号是通过2的幂算法(powers-of-two)得到的,而不是通过模数算法。
 
create table t4(

a int,

b datetime

)engine=innodb

partition by key (b)

partitions 4;

columns分区


MySQL5.5版本开始支持columns分区,可以看做range分区和list分区的一种进化。
columns分区可以直接使用非整型的数据进行分区,分区根据类型直接比较而得,不需要转化为整型。
columns分区支持以下的数据类型:
1、所有的整数类型,如int,smallint,tinyint,mediumint,bigint。float和decimal则不予支持
2、日期类型,如date和datetime。其余的日期类型不予支持。
3、字符串类型,如char,varchar,binary和varbinary。blob和text类型不予支持。

range columns

create table t5(

a int,

b datetime

)engine=innodb

partition by range columns (b) (

partition p0 values less than ('2009-01-01'),

partition p1 values less than ('2010-01-01')

);

range columns 分区可以对多个列的值进行分区。

create table t5_rcx(

a int,

b int,

c char(3),

d int

)engine=innodb

partition by range columns (a,d,c) (

partition p0 values less than (5, 10, 'ggg'),

partition p1 values less than (10, 20, 'mmm'),

partition p2 values less than (15, 20, 'sss'),

partition p3 values less than (maxvalue, maxvalue, maxvalue)

);

list columns 中文也可以

create table t6(

first_name varchar(25),

last_name varchar(25),

street_1 varchar(30),

street_2 varchar(30),

city varchar(15),

renewal date

)engine=innodb

partition by list columns (city) (

partition pRegion_1 values in ('北京','上海','广州'),

partition pRegion_2 values in ('武汉','郑州','成都')

);

子分区


子分区是指在分区的基础上再进行分区,也称该分区为复合分区。MySQL允许在range和list的分区上再进行hash和key的子分区。

子分区建立需要注意以下几个问题:
1、每个子分区的数量必须相同
2、要在一个分区表的任何分区上使用subpartition明确定义任何子分区,就必须定义所有的子分区。
3、每个subpartition子句必须包括子分区的一个名字
4、子分区的名字必须是唯一的。

b列进行range分区,又进行了一次hash分区,分区的数量是(3 x 2 = 6)

create table ts(

a int,

b date

)engine=innodb

partition by range (YEAR(b))

subpartition by hash(TO_DAYS(b))

subpartitions 2

(

partition p0 values less than (1990),

partition p1 values less than (2000),

partition p2 values less than maxvalue

);

我们也可以使用subpartition语法显示的指出各个子分区的名字:


create table dspy_sub_name(

a int,

b date

)engine=innodb

partition by range (YEAR(b))

subpartition by hash (TO_DAYS(b))

(

partition p0 values less than (2009) (

subpartition s0,

subpartition s1

),

partition p1 values less than (2010) (

subpartition s2,

subpartition s3

),

partition p2 values less than maxvalue (

subpartition s4,

subpartition s5

)

);

子分区可以用于特别大的表,在多个磁盘间分别分配数据和索引。假设有6个磁盘,分别为/disk0,/disk1,/disk2等,现在考虑下面的例子:


create table ts1(

a int,

b date

)engine=innodb

partition by range (YEAR(b))

subpartition by hash (TO_DAYS(b))

(

partition p0 values less than (2009) (

subpartition s0

DATA DIRECTORY = '/disk0/data'

INDEX DIRECTORY = '/disk0/idx',

subpartition s1

DATA DIRECTORY = '/disk1/data'

INDEX DIRECTORY = '/disk1/idx'

),

partition p1 values less than (2010) (

subpartition s2

DATA DIRECTORY = '/disk2/data'

INDEX DIRECTORY = '/disk2/idx',

subpartition s3

DATA DIRECTORY = '/disk3/data'

INDEX DIRECTORY = '/disk3/idx'

),

partition p2 values less than (2011) (

subpartition s4

DATA DIRECTORY = '/disk4/data'

INDEX DIRECTORY = '/disk4/idx',

subpartition s5

DATA DIRECTORY = '/disk5/data'

INDEX DIRECTORY = '/disk5/idx'

)

);

由于innodb存储引擎使用表空间自动的进行数据和索引的管理,因此会忽略DATA DIRECTORY 和INDEX DIRECTORY语法,因此上述分区表的数据和索引文件的分开放置对其是无效的。

分区中的null值


mysql数据库允许对null值做分区。MySQL数据库的分区总是把null值看做是小于任何一个非null值,这和MySQL数据库中处理null值得order by操作是一样的。因此对于不同的分区类型,MySQL数据库对于null值的处理也是不相同的。
1、对于range分区,如果向分区中插入null值,则MySQL数据库会将该值放入最左边的分区,另外注意的是如果删除最左边的分区,则会删除该分区的记录包括null值的记录
2、list分区下要使用null值,则必须显示地指出哪个分区中放入null值,否则会报错。

3、hash和key分区对于null的处理方式和range分区、list分区不一样。任何分区的函数都会将含有null值得记录返回为0

 
create table t(

int a,

int b

)engine=innodb

partition by list (b) (

partition p0 values in (1,3,5,7,9,null),

partition p1 values in (0,2,4,6,8)

);

在表和分区间交换数据


MySQL5.6开始支持alter table table_name exchange partition partition_name with table table_name的语法。该语法允许分区或子分区中的数据与另一个非分区的表中的数据进行交换。如果表中的数据为空,那么相当于将分区中的数据移动到非分区表中。若分区表中的数据为空,则相当于将外部表中的数据导入到分区中。
要使用这个语法要满足以下条件:
1、要交换的表必须和分区表有相同的表结构,但是要交换的表不能含有分区
2、在非分区表中的数据必须在交换的分区定义内
3、被交换的表中不能含有外键或者其他的表含有对该表的外键引用
4、用户除了需要alter,insert,create权限外,还需要有drop权限
另外,有两个小细节需要注意:
1、使用该语句时不会触发交换表和被交换表上的触发器
2、auto_increment列将被重置

 
create table e(

id int not null,

fname varchar(30),

lname varchar(30)

)engine=innodb

partition by range (id) (

partition p0 values less than (50),

partition p1 values less than (100),

partition p2 values less than (150),

partition p3 values less than maxvalue

);

--- 插入数据

insert into e values

(1669, 'Jim', 'Smith'),

(337, 'Mary', 'Jones'),

(16, 'Frank', 'White'),

(2005, 'Jerry', 'Tom');

--- 创建e2表,复制e表结构,并清除partition

create table e2 like e;

alter table e2 remove partitioning;

--- 交换数据

alter table e exchange partition p0 with table e2;

备注:一个分区只能交换到一个外部物理表中,不能将多个分区交换到同一个表。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/754816.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ios 启动页storyboard 使用记录

本文简单记录ios启动页storyboard 如何使用和注意事项。 xcode窗口简介 以xcode14为例,新建项目如下图,左边文件栏中的LaunchScreen.storyboard 为默认启动页布局。窗口中间部分是storyboard中的组件列表,右侧为预览,可以看到渲…

H3C-Cloud Lab-实验-DHCP实验

实验拓扑图: 实验需求: 1、按照图示为R1配置IP地址 2、配置R1为DHCP服务器,提供服务的地址池为192.168.1.0/24网段,网关为192.168.1.254,DNS服务器地址为202.103.24.68,202.103.0.117 3、192.168.1.10-1…

Camtasia Studio 2023 最新中文版,camtasiaStudio如何添加背景音乐

Camtasia2023的视频编辑工具可以帮助用户剪辑、裁剪、旋转、调整大小、添加特效、混合音频等。用户还可以使用Camtasia2023的字幕功能添加字幕和注释,以及使用其内置的特效和转场来提高视频的视觉效果。 Camtasia Studio 2023新功能介绍 的光标增强 由于光标在屏幕…

解决win10电脑无法访问局域网内其它共享文件问题

问题描述 今天需要上传文件到一个共享的局域网文件夹里,在我的电脑和浏览器访问//192.168.0.16//public都提升访问受限,开始以为是因为用户没授权,后来一般沟通后,发现其它电脑都能正常访问的,所以确定是自己电脑配置…

Caerulein,17650-98-5,雨蛙肽,以三氟醋酸盐形式提供的十肽分子

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ Caerulein |雨蛙素,雨蛙肽,蓝肽| CAS:17650-98-5 | 纯度:95% ------雨蛙素结构式---- ----试剂参数信息--- CAS号:17650-98-5 外观(Appearance&a…

java中使用POI生成Excel并导出

注:本文章中代码均为本地Demo版本,若后续代码更新将不会更新文章 需求说明及实现方式 根据从数据库查询出的数据,将其写入excel表并导出 我的想法是通过在实体属性上写自定义注解的方式去完成。因为我们在代码中可以通过反射的方式去获取实体…

js小写金额转大写 自动转换

// 小写转为大写convertCurrency(money) {var cnNums [零, 壹, 贰, 叁, 肆, 伍, 陆, 柒, 捌, 玖]var cnIntRadice [, 拾, 佰, 仟]var cnIntUnits [, 万, 亿, 兆]var cnDecUnits [角, 分, 毫, 厘]// var cnInteger 整var cnIntLast 元var maxNum 999999999999999.9999var…

vulnhub靶场red:1教程

靶场搭建 靶机下载地址:Red: 1 ~ VulnHub 难度:中等 信息收集 arp-scan -l 这里没截图忘记了,就只是发现主机 扫描端口 nmap --min-rate 1000 -p- 192.168.21.130 nmap -sT -sV -sC -O -p22,80 192.168.21.130 先看80端口 看到链接点一…

怎么又快又准的确定业务系统属于等保几级?

等保2.0政策已经落地严格执行了一段时间,但大家对于等保政策还有很多不清楚。这不不少人在问,怎么又快有准的确定业务系统属于等保几级? 怎么又快又准的确定业务系统属于等保几级? 【回答】:根据《信息安全等级保护管…

AtcoderABC255场

A - You should output ARC, though this is ABC.A - You should output ARC, though this is ABC. 题目大意 给定整数R和C以及一个2x2矩阵A,需要输出A R,C的值。 思路分析 简单的矩阵查找。根据给定的索引R和C,找到矩阵A中相应位置的元素&#xff0c…

实例014 OutLook界面

实例说明 程序主界面包括菜单栏、工具栏、状态栏和树状视图。OutLook界面美观、友好,是一个很实用的程序主界面,并且菜单栏和工具栏是可移动的。运行本例效果如图1.14所示。 图1.14 Out Look界面 技术要点 一般程序的菜单栏和工具栏是不可移动的&…

【Ajax】笔记-服务端响应JSON数据

服务端响应JSON数据 构建测试案例 键盘按键触发请求服务端&#xff1a; 键盘按下触发事件 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,…

项目中前端如何实现无感刷新 token!

场景&#xff1a;线上平台有时会出现用户正在使用的时候&#xff0c;突然要用户去进行登录&#xff0c;这样会造成很不好的用户体验。 1.请求采用的是axios 2.平台的采用的 JWT(JSON Web Tokens) 进行用户登录鉴权。 原因&#xff1a; 1.突然跳转到登录页面&#xff0c;是…

【IVI】EVS 应用

EVS 应用 1、EVS启动2、EvsStateControl.cpp 控制管理2.1 EvsStateControl初始化2.2 EvsVehicleListener.h唤起处理EvsStateControl::updateLoop() 3、EVS 应用逻辑流程 android12-release 增强型视觉系统 (EVS) 1、EVS启动 Android 包含与 EVS 管理器和车载 HAL 通信的 EVS 应…

CAD2021安装教程适合新手小白【附安装包和手册】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、下载文件二、使用步骤1.安装软件前&#xff0c;断开电脑网络&#xff08;拔掉网线、关闭WIFI&#xff09;2、鼠标右击【AutoCAD2021(64bit)】压缩包选择【解…

解密:GPT-4框架与训练过程,数据集组成,并行性的策略,专家权衡,推理权衡等细节内容

大家好&#xff0c;我是微学AI&#xff0c;今天给大家解密一下GPT-4框架与训练过程&#xff0c;数据集组成&#xff0c;并行性的策略&#xff0c;专家权衡&#xff0c;推理权衡等细节内容。2023年3月14日&#xff0c;OpenAI发布GPT-4&#xff0c;然而GPT-4的框架没有公开&#…

Nacos服务注册和配置中心(Config,Eureka,Bus)2

Nacos数据模型 Nacos领域模型,Namespace命名空间、Group分组、集群这些都是为了进行归类管理&#xff0c;把服务和配置文件进行归类&#xff0c;归类之后就可以实现一定的效果&#xff0c;比如隔离。对于服务来说&#xff0c;不同命名空间中的服务不能够互相访问调用 N…

msvcr110.dll丢失的解决方法分享,教你如何快速解决

首先介绍msvcr110.dll是什么&#xff1f;下面再介绍解决方法。 msvcr110.dll文件它提供了一系列用于C编程的函数和资源。这个文件通常用于支持使用了C语言编写的程序&#xff0c;如一些游戏、图形应用程序、数据库管理工具等。 与msvcp110.dll文件类似&#xff0c;msvcr110.dl…

Linux系统编程(守护进程)

文章目录 前言一、守护进程概念二、空洞文件三、创建守护进程总结 前言 本篇文章我们来讲解守护进程&#xff0c;守护进程在进程中是一个比较重要的概念&#xff0c;在笔试面试中也经常考到&#xff0c;这篇文章就带大家来学习一下什么是守护进程。 一、守护进程概念 守护进…

golang IDE 使用 go-1.7 无法识别 goroot问题

问题 当前使用了 golang IDE 要设定 go-1.17 版本作为默认 GOROOT 系统环境变量已经定义好 打开了 ide 会出现下面问题&#xff0c;选择 1.17 后会出现下面报错 error message The selected directory is not a valid horne for GO SDK 解决方法 修改 $GOROOT 下文件增加一个变…