mysql 分区分表_mysql分库分区分表

article/2025/10/27 19:49:45

一、分表

分表分为水平分表和垂直分表。

水平分表原理:

c8f63c4a9ee0b59124003f6172df1da9.png

 分表策略通常是用户ID取模,如果不是整数,可以首先将其进行hash获取到整。

水平分表遇到的问题:

1. 跨表直接连接查询无法进行

2. 我们需要统计数据的时候

3. 如果数据持续增长,达到现有分表的瓶颈,需要增加分表,此时会出现数据重新排列的情况

解决方案建议:

1. 第1,2点可以通过增加汇总的冗余表,虽然数据量很大,但是可以用于后台统计或者查询时效性比较底的情况,而且我们可以提前算好某个时间点或者时间段的数据

2. 第3点解决建议:

1. 可以开始的时候,就分析大概的数据增长率,来大概确定未来某段时间内的数据总量,从而提前计算出未来某段时间内需要用到的分表的个数

2. 考虑表分区,在逻辑上面还是一个表名,实际物理存储在不同的物理地址上

3. 分库

垂直拆分原则:

1. 把大字段独立存储到一张表中

2. 把不常用的字段单独拿出来存储到一张表

3. 把经常在一起使用的字段可以拿出来单独存储到一张表

e3afc8c59cf7cc5bce014eb669e65807.png

垂直拆分标准

1.表的体积大于2G并且行数大于1千万

2.表中包含有text,blob,varchar(1000)以上

3.数据有时效性的,可以单独拿出来归档处理

表的体积计算

CREATE TABLE `test1` (id bigint(20) not null auto_increment,detail varchar(2000),createtime  datetime,validity int default '0',primary key (id));

1000万  bigint 8字节 varchar 2000 字节 datetime  8字节 validity 4字节

(8+2000+8+4) * 10000000 = 20200000000 字节 == 18G

分表后体积:

CREATE TABLE `test1` (id int not null auto_increment,createtime  timestamp,validity tinyint default 0,primary key (id));

计算:(4+4+1) * 10000000 =  0.08G

表分区:

        就是将一个数据量比较大的表,用某种方法把数据从物理上分成若干个小表来存储(类似水平分表),从逻辑来看还是一个大表。分表最大分1024,一般分100左右比较适合。

使用场景:

对于这种数据库比较多,但是并发不是很多的情况下,可以采用表分区。

对于数据量比较大的,但是并发也比较高的情况下,可以采用分表和分区相结合。

二、分库

分库策略与分表策略的实现很相似,最简单的都是可以通过取模的方式进行路由。

分库也可以按照业务分库,比如订单表和库存表在两个库,要注意处理好跨库事务。

分表和分库 同时实现。

分库分表的策略相对于前边两种复杂一些,一种常见的路由策略如下:

1、中间变量 = user_id%(库数量*每个库的表数量);

2、库序号 = 取整(中间变量/每个库的表数量);

3、表序号 = 中间变量%每个库的表数量;

例如:数据库有256 个,每一个库中有1024个数据表,用户的user_id=262145,按照上述的路由策略,可得:

1、中间变量 = 262145%(256*1024)= 1;

2、库序号 = 取整(1/1024)= 0;

3、表序号 = 1%1024 = 1;

这样的话,对于user_id=262145,将被路由到第0个数据库的第1个表中。

range分区

create table test_range(id int not null default 0)engine=myisam default charset=utf8partition by range(id)(partition p1 values less than (3),partition p2 values less than (5),partition p3 values less than maxvalue);

hash分区

create table test_hash(id int not null default 0)engine=innodb default charset=utf8partition by hash(id) partitions 10;

线性hash分区

create table test_linear(id int not null default 0)engine=innodb default charset=utf8partition by linear hash(id) partitions 10;

list分区

create table test_list(id int not null) engine=innodb default charset=utf8partition by list(id)(partition p0 values in (3,5),partition p1 values in (2,6,7,9));

key 分区

CREATE TABLE test_key (col1 INT NOT NULL)PARTITION BY  linear KEY (col1)PARTITIONS 10;

普通的hash分区 增加风区后,需要重新计算

线性hash分区(了解)   增加分区后,还是在原来的分区

线性hash 相对于 hash分区 没有那么均匀

Key分区用的比较少,也是hash分区

三、HASH分区与线性HASH分区区别

        对于HASH分区,需要关注两点,第一:用于HASH计算的一个或者多个列值或者基于一个或者多个列值的表达式expr,第二:表的分区数,也就是表应该被分成几个分区。对于第一点MySQL使用PARTITION BY HASH (expr)语句来定义,HASH用于计算expr的哈希值,expr是一个或者多个整数列或者是一个返回整数的表达式,对于第二点使用PARTITIONS num语句来指定分区数,num表示分区数,是一个正整数。例如,对于employees表,按照整数类型的字段store_id的值分成4个分区,可如下创建HASH分区表:

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 HASH(store_id)
PARTITIONS 4;

如果没使用PARTITIONS子句,employees表默认只有1个分区,即如下两种方式是等价的:

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 HASH(store_id)
;
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 HASH(store_id)
PARTITIONS 1;

如果使用了PARTITIONS,而没有指定分区数,是存在语法错误的。

可以在非整数类型字段,但返回整数的表达式上使用HASH分区,例如:

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 HASH( YEAR(hired) )
PARTITIONS 4;

hired是DATE类型,但YEAR()函数返回一个整数。

        PARTITION BY HASH (expr)是如何计算每条记录的分区的呢?对于给定的一条数据行,先计算数据行的列对应的表达式expr的值,然后使用表达式的值对分区数num进行取模运行,即n=MOD(expr, num),得到的值n就是数据行的分区号,最后该数据行就存储到分区号为n的分区中。下面举个例子,假设表t1有4个分区,HASH分区建表语句如下:

CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE)
PARTITION BY HASH( YEAR(col3) )
PARTITIONS 4;

向HASH分区表t1插入如下一条记录:

insert into t1 values(1,'2','2005-09-15');

如下方式可计算该条记录的分区号:

MOD(YEAR('2005-09-01'),4)
=  MOD(2005,4)
=  1

可以执行如下语句进行验证:

select PARTITION_NAME,TABLE_ROWS 
from information_schema.`PARTITIONS` where `TABLE_NAME`='t1';
说明:t1 为表名

 该数据行存储在分区p1中。

LINEAR HASH分区 

         与HASH分区不同,LINEAR HASH分区使用了线性2的幂(linear powers-of-two)算法。但LINEAR HASH分区创建的语法与HASH分区确十分相似,如下:

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 LINEAR HASH( YEAR(hired) )
PARTITIONS 4;

仅仅是在HASH关键词前添加LINEAR关键词。那么对于LINEAR HASH分区,数据行是如何存储到对应分区的呢?下面我们详细解释线性2的幂算法。假设给定表达式expr和分区数num,

(1)找到比num大的最小2的幂,假设num=1,那么比1大的最小2的幂是2,即2^1,假设num=13,比num大的最小2的是16,即2^4,可以通过如下公式计算:

V = POWER(2, CEILING(LOG(2, num)))

LOG是对数函数,CEILING(x)是取比x大的最小整数。

(2)N = expr & (V - 1)

列值对应的表达式expr的值与(V-1)求“与”运算,得到分区号N;

(3)如果上一步计算得到的分区号小于num,数据行存储到分区号N的分区中,如果分区号大于或者等于num,继续计算

  • 设置 V = V / 2

  • 设置 N = N & (V - 1)

循环执行(3)。

下面举例说明该算法:

创建一个分区数为6的LINEAR HASH分区表t1,如下:

CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE)
PARTITION BY LINEAR HASH( YEAR(col3) )
PARTITIONS 6;

 1、向分区表中插入如下数据:

insert into t1 VALUES(1,'1','2003-04-14');

下面使用线性2的幂算法,计算该数据的分区号

(1)分区数num=6,计算出V值:

V = POWER(2, CEILING( LOG(2,6) )) = 8

2) 计算出分区号N

N = YEAR('2003-04-14') & (8 - 1)= 2003 & 7= 3

3) 因为N<6,所以数据行存储到分区号3中,即p3分区(分区号从0开始计算),可以执行如下sql进行验证

select PARTITION_NAME,TABLE_ROWS 
from information_schema.`PARTITIONS` where `TABLE_NAME`='t1';

2、向分区中再插入如下一条数据:

insert into t1 VALUES(2,'2','1998-10-19');

 (1)计算V值

V = 8

(2)计算分区号N 

N = YEAR('1998-10-19') & (8 - 1)= 1998 & 7= 6

3)N≥num,重新设置V,计算分区号N

V = 8/2=4
N = N & (V - 1)= 6 & (4 - 1)= 6 & 3= 2

所以数据行存储到分区号2中,验证结果如图:


http://chatgpt.dhexx.cn/article/QpLQBpmc.shtml

相关文章

Mock平台介绍

Mock平台可以用来模拟接口&#xff0c;具备了get方法&#xff0c;post方法&#xff0c;header&#xff0c;cookie&#xff0c;重定向等功能。 Mock平台的搭建应用于mock框架&#xff0c;在github上可以下载到开源的代码。 下载地址&#xff1a;http://repo1.maven.org/maven2/…

Mock 框架 Moq 的使用

Intro# Moq 是 .NET 中一个很流vb.net教程行的 Mock 框架&#xff0c;使c#教程用 Mock 框架我python基础教程们可以只针对我java基础教程们关注的代码进行测试&#xff0c;对于sql教程依赖项使用 Mock 对象配置预期的依赖服务的行为。 Moq 是基于 Castle 的动态代理来实现的&…

mockjs入门

mockjs 1,mock.js是什么&#xff1f; mockjs是生成随机数据的一款前端工具&#xff0c;用来模拟 Ajax 请求&#xff0c;生成并返回模拟数据 2&#xff0c;为什么用mockjs&#xff1f; 当程序员做项目开发时&#xff0c;前端工程师要请求后端做好的数据时&#xff0c;有可能…

monkey简介

https://blog.csdn.net/lebang08/article/details/70858532 https://www.cnblogs.com/aland-1415/p/6949964.html https://blog.csdn.net/aisemi/article/details/55254348 一、Monkey 简介 monkey是Android SDK中自带的一个命令行工具&#xff0c;使用Java语言写成&#xf…

mokey的介绍和使用

一、monkey介绍 monkey是Android SDK提供的一个命令行工具&#xff0c;可以简单方便的发送伪随机的用户时间流&#xff0c;对Android APP做压力&#xff08;稳定性、健壮性&#xff09;测试。主要是为了测试APP是否存在无响应和崩溃的情况。 二、monkey的使用 1、前提条件&a…

APP测试— 测试工具mokey

文章目录 1 Mokey概念2 运行Monkey&#xff08;对手机进行300次无规律点击&#xff09;3 Mokey常规参数4 Monkey 事件类参数5 Monkey 约束类参数 1 Mokey概念 1&#xff09;Monkey是Android SDK提供的一个命令行工具&#xff0c;可以简单、方便的运行任何版本的Android模拟器和…

Kafka配置用户名密码访问

1 软件版本 kafka_2.12-2.4.0.tgz&#xff08;带zookeeper&#xff09; 2 kafka服务端部署 2.1 将安装包上传到服务器&#xff0c;并解压 tar zxvf kafka_2.12-2.4.0.tgz -C /datamv kafka_2.12-2.4.0 kafka2.2 修改kafka配置文件 server.properties vim /data/kafka/conf…

linux 用户名和密码的处理

1. 创建新用户和密码 # 创建用户 testuser useradd testuser# 给已创建的用户testuser设置密码 passwd testuser# 新创建的用户会在 /home 下创建一个用户目录testuser# 修改用户这个命令的相关参数 usermod --help# 删除用户testuser userdel testuser# 删除用户所在目录rm -…

用户名,密码登录

1.导入项目需要的依赖&#xff0c;分层 注意&#xff1a;如果你的数据库是5.5的版本&#xff0c;依赖要用低版本的&#xff0c;高版本不稳定&#xff0c;新增的内容不识别&#xff0c;会报各种各样奇葩的错误 2.创建实体类 它的属性要和数据库字段对应 package com.oa.entity…

实现用户输入用户名和密码登录

题目 实现用户输入用户名和密码登录&#xff0c;当用户名为admin或administrator且密码为666666时&#xff0c;显示“登录成功”&#xff0c;否则显示“登录失败”&#xff0c;登录失败时允许重复输入三次。 实例 参考程序 User1 "admin" User2 "administr…

计算机用户名和初始密码,电脑默认的用户名和密码是多少

优质回答 回答者&#xff1a;止树2018 电脑用户默认是没有密码的&#xff0c;除非你设置了&#xff0c;没有设置的前提下&#xff0c;直接按回车键就可以进系统了。 电脑默认的用户是administrator&#xff0c;如果你创建了自己的新用户名&#xff0c;那么&#xff0c;原始管理…

服务器密码以及用户名怎么修改

服务器密码以及用户名怎么修改 我是艾西&#xff0c;今天给大家说下服务器密码如何修改 windows2003系统&#xff1a; 1、右键我的电脑&#xff0c;点击“管理”&#xff1a; 2、在“本地用户和组”中打开“用户”&#xff0c;在右侧找到 Administrator 账户进行修改。 200…

电脑更改开机密码和用户名

一、电脑更改开机密码 1、快捷键CtrlAltDel出现以下界面。 2、点击“更改密码”&#xff0c;出现修改密码的界面&#xff0c;输入旧的密码&#xff0c;以及新的密码&#xff0c;确定即可。 二、电脑更改开机用户名 1、打开电脑的”控制面板“。 2、在控制面板中点击“用户帐户…

基于51单片机的呼吸灯程序编写

利用51单片机编写的呼吸灯小程序&#xff0c;实验程序内容截图分享~

六、Arduino呼吸灯的实现

实验所需材料 Arduino UNO面包板LED灯一个330Ω电阻一个 连接示意图 如图所示&#xff0c;实验中我们将LED连接到了带PWM功能的D9引脚。 可以在 Arduino IDE菜单>文件>示例>03.Analog>Fading 打开呼吸灯示例程序&#xff0c;程序如下&#xff1a; int ledPin 9…

C语言实现呼吸灯(HAL库)

1. 呼吸灯原理 呼吸灯的实现可以通过控制灯的亮度连续变化&#xff0c;当变化的频率大于24帧时&#xff0c;肉眼看上去就会逐渐变暗&#xff0c;逐渐变亮。 2. PWM控制亮度 PWM通过设置亮度在一段时间内的占空比&#xff0c;亮的百分比多&#xff0c;人眼看到的就亮&#xf…

二、15【FPGA】呼吸灯实现

前言 学习说明此文档为本人的学习笔记&#xff0c;注重实践&#xff0c;关于理论部分会给出相应的学习链接。 学习视频&#xff1a;是根据野火FPGA视频教程——第十八讲 https://www.bilibili.com/video/BV1nQ4y1Z7zN?p3 实战演练 一、设计规划 1.1 实验目标 在开发板上…

基于FPGA实践之呼吸灯(含程序)

呼吸灯是指灯光在微电脑的控制之下完成由亮到暗的逐渐变化&#xff0c;感觉好像是人在呼吸。 在单片机中我们调节PWM波的占空比可以实现一个周期内高电平占百分比&#xff0c;这个百分比固定就可以调节亮度&#xff0c;这个百分比是动态的&#xff0c;那么灯的亮度也是动态的&…

Verilog实现呼吸灯效果

呼吸灯的效果采用PWM调波的形式&#xff0c;即快速的改变每个周期的占空比&#xff08;一个周期内高电平时间占一个周期时间的比值&#xff09;来实现点亮到熄灭的效果。示意如下图 而关于整个波形图&#xff0c;用50MHz的晶振&#xff0c;从0开始计数到49则为1us。 而1ms是1u…

呼吸灯

呼吸灯 呼吸灯&#xff0c;就是控制led灯的亮度从弱变强、从强变弱的循环往复&#xff0c;从而实现像呼吸一样的效果。改变电压即可改变led灯的亮度&#xff0c;但是用代码控制led灯两端电压显然是不现实的&#xff0c;我们可以用控制脉冲宽度的方式来控制led灯点亮的时间&…