Mysql优化之分区分表

为什么要分区分表

分区和分表是两种用于优化大型数据集查询性能的技术,它们有不同的应用场景和优势。随着数据库数据越来越大,单个表中数据太多。以至于查询速度变慢,而且由于表的锁机制导致应用操作也受到严重影响,就出现了数据库性能瓶颈。当出现这种情况时,我们可以考虑分表或分区。

mysql表锁定和行锁定,是为了保证数据的完整性。表锁定表示你们都不能对这张表进行操作,必须等我对表操作完才行。行锁定也一样,别的sql操作必须等我对这条数据操作完了,才能对这条数据进行操作。

分表

  • 分表是数据库优化技术之一,它将一个大表拆分成多个小表,每个小表只包含部分数据。这样做的目的是减少单个表中的数据量,提高查询性能、降低锁竞争,并且可以更灵活地管理数据。这些表可以分布在同一块磁盘上,也可以在不同的机器上。读写的时候根据事先定义好的规则得到对应的表名,然后去操作它。Mysql分表分为垂直切分和水平切分。

1、垂直切分:垂直切分是指数据表列的拆分,把一张列比较多的表拆分为多张表。通常我们按以下原则进行垂直拆分: 根据列的访问频率和关联性来进行划分。把不常用的字段单独放在一张表; 把text,blob等大字段拆分出来放在附表中;通常用于将大型宽表拆分成多个相对较小的窄表,以减少单个表的数据量和提高查询性能(减少查询时的数据量和锁竞争)。 垂直拆分更多时候就应该在数据表设计之初就执行的步骤。

2、水平切分:水平切分是指数据表行的拆分,把一张的表的数据拆成多张表来存放,每个表包含原表的一部分行。通常是根据某个列的值范围或者哈希值来进行划分。水平切分通常用于解决单个表数据量过大、性能瓶颈明显的情况。例如:一个包含大量用户的用户表可以根据用户所在地区进行水平切分,将不同地区的用户数据存储在不同的表中。这样可以降低单个表的数据量,提高查询性能和并发性能。

分表的几种方式

  1. 集群:它并不是分表,但起到了和分表相同的作用。集群可分担数据库的操作,将任务分担到多台数据库上。集群可以读写分离,减少读写压力从而提升数据库性能。
  2. 预先估计会出现大数据量并且访问频繁的表,将其分为若干个表。例如聊天的信息表:可以先预估有100个这样的表判断用户的ID将信息存入相应的表。也可以设计每张表的容量是X条,插入数据前进行判断小于X就直接插入数据,大于X就创建新表后插入数据。

垂直分表

  • 根据数据访问模式进行拆分:根据业务需求和数据访问模式来确定拆分的策略。将常用的列放在一个表中,不常用的列放在另一个表中,以提高查询性能和降低数据访问的复杂性。

  • 保持关联数据的完整性:如果需要将一个实体的数据拆分到多个表中,确保这些表之间的数据关联是完整的,可以通过主键和外键来保持数据的一致性。

  • 避免过度拆分:不要将数据拆分得过于细致,以免增加查询的复杂度和维护的成本。合理拆分可以提高性能,但过度拆分可能会导致额外的复杂性和性能损失。

  • 考虑扩展性:在进行垂直分表时,考虑到系统的扩展性,确保分表方案能够支持未来系统的扩展和变化,避免频繁的表结构调整和数据迁移。

  • 评估性能影响:在实施分表方案之前,进行性能评估和测试,确保分表方案能够达到预期的性能提升,并且不会引入新的性能问题。

  • 考虑维护成本:评估分表方案的维护成本,包括数据迁移、查询优化和系统维护等方面的成本。确保分表方案不会增加过多的维护工作量。

我这里有库查询一下最大的表:

mysql> select table_name as `table`,round(((data_length + index_length)/1024/1024),2) as `size (MB)` from infor+-----------------------+-----------+ma = 'bwk_test' order by (data_length + index_length) desc limit 1;
| table                 | size (MB) |
+-----------------------+-----------+
| tb_charm_value_record |    119.06 |
+-----------------------+-----------+
1 row in set (0.18 sec)

查询一下表的结构数据:

mysql> select table_name,engine,table_collation from information_schema.tables where table_schema='bwk_test' and table_name='tb_charm_value_record';
+-----------------------+--------+--------------------+
| TABLE_NAME            | ENGINE | TABLE_COLLATION    |
+-----------------------+--------+--------------------+
| tb_charm_value_record | InnoDB | utf8mb3_general_ci |
+-----------------------+--------+--------------------+

查询表键属性:

mysql> desc tb_charm_value_record;
+--------------------+---------------+------+-----+-------------------+-----------------------------------------------+
| Field              | Type          | Null | Key | Default           | Extra                                         |
+--------------------+---------------+------+-----+-------------------+-----------------------------------------------+
| CharmValueRecordID | varchar(50)   | NO   | PRI | NULL              |                                               |
| TaskID             | varchar(50)   | YES  | MUL | NULL              |                                               |
| UserID             | varchar(50)   | YES  | MUL | NULL              |                                               |
| CharmValue         | decimal(10,2) | YES  |     | NULL              |                                               |
| CharmType          | int           | YES  |     | NULL              |                                               |
| IsReceive          | bit(1)        | YES  |     | NULL              |                                               |
| ReceiveTime        | datetime      | YES  |     | NULL              |                                               |
| CreationTime       | datetime      | NO   |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED                             |
| Creator            | varchar(50)   | NO   |     | NULL              |                                               |
| RevisionTime       | datetime      | NO   |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED on update CURRENT_TIMESTAMP |
| Reviser            | varchar(50)   | NO   |     | NULL              |                                               |
| Remark             | varchar(50)   | YES  |     | NULL              |                                               |
| CharmInAndOut      | int           | NO   |     | NULL              |                                               |
| Currency           | int           | YES  |     | 5                 |                                               |
| OperationID        | varchar(50)   | YES  |     | NULL              |                                               |
+--------------------+---------------+------+-----+-------------------+-----------------------------------------------+
15 rows in set (0.01 sec)

创建分表:tb_charm_value_record_1、tb_charm_value_record_2、tb_charm_value_record_3

create table tb_charm_value_record_1 (CharmValueRecordID varchar(50) not null primary key, TaskID varchar(50),UserID varchar(50), CharmValue decimal(10,2),CharmType int ,IsReceive bit(1)) engine=innodb  charset=utf8mb3 collate=utf8mb3_general_ci; create table tb_charm_value_record_2 (CharmValueRecordID varchar(50) not null primary key, ReceiveTime datetime, CreationTime datetime not null default current_timestamp,Creator varchar(50) not null ,RevisionTime datetime not null default current_timestamp on update current_timestamp) engine=innodb  charset=utf8mb3 collate=utf8mb3_general_ci; create table tb_charm_value_record_3 (CharmValueRecordID varchar(50) not null primary key, Reviser varchar(50) not null, Remark varchar(50), CharmInAndOut int not null, Currency int,OperationID varchar(50)) engine=innodb  charset=utf8mb3 collate=utf8mb3_general_ci; 

创建分表关联视图:

create view tb_charm_value_record_viem_time(CharmValueRecordID,UserID,CharmValue,ReceiveTime,Remark) as select t_1.CharmValueRecordID,t_1.UserID,t_1.CharmValue,t_2.ReceiveTime,t_3.Remark from tb_charm_value_record_1 as t_1 join  tb_charm_value_record_2 t_2 on t_1.CharmValueRecordID=t_2.CharmValueRecordID join tb_charm_value_record_3 t_3 on t_1.CharmValueRecordID=t_3.CharmValueRecordID;

查询数据核查:

mysql> select CharmValueRecordID,UserID,CharmValue,ReceiveTime,Remark from tb_charm_value_record where CharmValueRecordID='00018ece9f834ea288d3be23a39ef870';
+----------------------------------+----------------------------------+------------+---------------------+--------+
| CharmValueRecordID               | UserID                           | CharmValue | ReceiveTime         | Remark |
+----------------------------------+----------------------------------+------------+---------------------+--------+
| 00018ece9f834ea288d3be23a39ef870 | 1fd33b53837946849ffc4ad73f4df747 |       5.00 | 2022-06-20 07:30:35 |        |
+----------------------------------+----------------------------------+------------+---------------------+--------+
1 row in set (0.00 sec)mysql> select CharmValueRecordID,UserID,CharmValue,ReceiveTime,Remark from tb_charm_value_record_viem_time where CharmValueRecordID='00018ece9f834ea288d3be23a39ef870';
+----------------------------------+----------------------------------+------------+---------------------+--------+
| CharmValueRecordID               | UserID                           | CharmValue | ReceiveTime         | Remark |
+----------------------------------+----------------------------------+------------+---------------------+--------+
| 00018ece9f834ea288d3be23a39ef870 | 1fd33b53837946849ffc4ad73f4df747 |       5.00 | 2022-06-20 07:30:35 |        |
+----------------------------------+----------------------------------+------------+---------------------+--------+
1 row in set (0.00 sec)

水平分表

  • 按照行范围拆分:根据某个范围条件,将数据拆分到不同的物理表中。例如,可以根据时间范围、用户 ID 范围等将数据拆分到不同的表中。
  • 按照哈希拆分:根据某个哈希函数将数据拆分到不同的物理表中。这样可以均匀地将数据分布到不同的表中,避免单一表数据过大的问题。
  • 按照业务逻辑拆分:根据业务需求将数据拆分到不同的物理表中。例如,可以根据商品类别、地区或者用户等级等将数据拆分到不同的表中。

按照表中:CreationTime 时间来进行拆分成2022年和2023年的两个表。

create table tb_charm_value_record_2022 (CharmValueRecordID varchar(50) not null primary key, TaskID varchar(50),UserID varchar(50), CharmValue decimal(10,2),CharmType int ,IsReceive bit(1),ReceiveTime datetime, CreationTime datetime not null default current_timestamp,Creator varchar(50) not null ,RevisionTime datetime not null default current_timestamp on update current_timestamp,Reviser varchar(50) not null, Remark varchar(50), CharmInAndOut int not null,Currency int,OperationID varchar(50)) engine=innodb  charset=utf8mb3 collate=utf8mb3_general_ci; 

修改table tb_charm_value_record_2022为2023在创建2023表

插入数据:

insert into  tb_charm_value_record_2022 (CharmValueRecordID, TaskID, UserID, CharmValue, CharmType, IsReceive, ReceiveTime, CreationTime, Creator, RevisionTime, Reviser, Remark, CharmInAndOut, Currency, OperationID) select CharmValueRecordID, TaskID, UserID, CharmValue, CharmType, IsReceive, ReceiveTime, CreationTime, Creator, RevisionTime, Reviser, Remark, CharmInAndOut, Currency, OperationID FROM tb_charm_value_record WHERE YEAR(ReceiveTime) = 2022;

修改时间插入2023的数据

对数据分表前要做好备份,最后对数据进行详细核查。

分区

分区和分表相似,都是按照规则分解表。不同在于分表将大表分解为若干个独立的实体表,而分区是将数据分段划分在多个位置存放,分区后,表还是一张表,但数据散列到多个位置了。程序读写的时候操作的还是表名字,数据库自动去组织分区的数据。

1、性能提升: 可以将数据分散到多个物理存储介质上,从而提高并发读写操作的性能。
2、数据管理: 可以针对不同的分区实施不同的数据管理策略,例如备份、恢复、优化和维护等。
3、数据清理: 可以轻松地删除或移动某些分区中的数据,而不会影响其他分区的数据。
4、提高可用性: 可以根据应用需求将不同的分区放置在不同的物理存储设备上,以提高系统的可用性和容错性。

分区主要有两种形式:

  • 水平分区(Horizontal Partitioning)这种形式分区是对表的行进行分区,所有在表中定义的列在每个数据集中
    都能找到,所以表的特性依然得以保持。

  • 垂直分区(Vertical Partitioning)这种分区方式一般来说是通过对表的垂直划分来减少目标表的宽度,使某些
    特定的列被划分到特定的分区,每个分区都包含了其中的列所对应的行

创建分区表:

create table tb_charm_value_record_p (CharmValueRecordID varchar(50) not null , TaskID varchar(50),UserID varchar(50), CharmValue decimal(10,2),CharmType int ,IsReceive bit(1),ReceiveTime datetime, CreationTime datetime not null default current_timestamp,Creator varchar(50) not null ,RevisionTime datetime not null default current_timestamp on update current_timestamp,Reviser varchar(50) not null, Remark varchar(50), CharmInAndOut int not null,Currency int,OperationID varchar(50), primary key(CharmValueRecordID,CharmType)) engine=innodb  charset=utf8mb3 collate=utf8mb3_general_ci partition by range(CharmType) (partition p0 values less than(5),partition p1 values less than(10), partition p2 values less than(maxvalue));

导入数据:

insert into  tb_charm_value_record_p (CharmValueRecordID, TaskID, UserID, CharmValue, CharmType, IsReceive, ReceiveTime, CreationTime, Creator, RevisionTime, Reviser, Remark, CharmInAndOut, Currency, OperationID) select CharmValueRecordID, TaskID, UserID, CharmValue, CharmType, IsReceive, ReceiveTime, CreationTime, Creator, RevisionTime, Reviser, Remark, CharmInAndOut, Currency, OperationID FROM tb_charm_value_record;

查看数据存储:

[root@mysql bwk_test]# ls | grep tb_charm_value_record_p
tb_charm_value_record_p#p#p0.ibd
tb_charm_value_record_p#p#p1.ibd
tb_charm_value_record_p#p#p2.ibd

mysql分表和分区有什么区

1)实现方式上:

1、mysql的分表是真正的分表,一张表分成很多表后,每一个小表都是完整的一张表。
2、分区不一样,一张大表进行分区后,他还是一张表,不会变成二张表,但是他存放数据的区块变多了

2)数据处理上:

1、分表后,数据都是存放在分表里,存取数据发生在一个一个的分表里面。
2、分区呢,不存在分表的概念,分区只不过把存放数据的文件分成了许多小块,分区后的表呢,还是一张表,数据处理还是由自己来完成。

3)提高性能上:

1、分表后,单表的并发能力提高了,磁盘I/O性能也提高了。并发能力为什么提高了呢,因为查寻一次所花的时间变短了,如果出现高并发的话,总表可以根据不同的查询,将并发压力分到不同的小表里面。
2、mysql提出了分区的概念,主要是想突破磁盘I/O瓶颈,想提高磁盘的读写能力,来增加mysql性能。在这一点上,分区和分表的测重点不同,分表重点是存取数据时,如何提高mysql并发能力上;而分区呢,如何突破磁盘的读写能力,从而达到提高mysql性能的目的。

4)都能提高mysql的性高,在高并发状态下都有一个良好的表现。

5)分表和分区不矛盾,可以相互配合的,对于那些大访问量,并且表数据比较多的表,我们可以采取分表和分区结合的方式,访问量不大,但是表数据很多的表,我们可以采取分区的方式等。

6、分表技术是比较麻烦的,需要手动去创建子表,app服务端读写时候需要计算子表名。采用merge好一
些,但也要创建子表和配置子表间的union关系。

7、表分区相对于分表,操作方便,不需要创建子表。

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

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

相关文章

springboot 批量下载文件, zip压缩下载

一、使用hutool 工具类 效果&#xff1a;下载速度可以 1、依赖&#xff1a;hutool <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.26</version> </dependency>2、调用方式 im…

Android Studio开发工具学习之Git分支操作

这里写目录标题 2.1 查看、创建本地分支2.1.1 命令行查看与创建2.1.2 Git窗口查看与创建 2.2 切换分支&#xff1a;Checkout2.3.1 通过命令行切换 2.3.2 通过Git窗口切换 2.3 合并分支&#xff1a;Merge2.3.1 操作command_new、gui-new分支2.3.1 通过命令行将gui-new分支合并至…

Day35代码随想录贪心part04:860.柠檬水找零、406.根据身高重建队列、452. 用最少数量的箭引爆气球

Day35 贪心part04 860.柠檬水找零 leetcode题目链接&#xff1a;860. 柠檬水找零 - 力扣&#xff08;LeetCode&#xff09; **复习一下dict的语法&#xff1a;**wallet[i] wallet.get(i, 0)1 本题一开始尝试用逐层判断去做&#xff0c;但这样好像并不合理 思路&#xff1…

深度学习网络训练,Loss出现Nan的解决办法

文章目录 前言 一、原因 二、典型实例 1. 梯度爆炸 2. 不当的损失函数 3. 不当的输入 前言 模型的训练不是单纯的调参&#xff0c;重要的是能针对出现的各种问题提出正确的解决方案。本文就训练网络loss出现Nan的原因做了具体分析&#xff0c;并给出了详细的解决方案&#xff…

LT8711UXD助力新款Swtich游戏机底座《4K/60HZ投屏方案》

Nintendo Switch&#xff08;OLED版&#xff09;正面搭载了一块分辨率为720P的7.0英寸OLED屏幕&#xff1b;具有白色和电光蓝电光红2种颜色&#xff1b;机身长度102毫米&#xff0c;宽度242毫米&#xff0c;厚度13.9毫米&#xff0c;重量约420克。 [2]Nintendo Switch&#xff…

举个栗子!Tableau 技巧(271):同时筛选不同年份的 TopN 数据

零售企业的销售数据分析中&#xff0c;经常用排序来查看过去一年或者几年的数据 TopN 情况。如果可以在同一视图中&#xff0c;呈现很多年的数据排名&#xff0c;且通过筛选能灵活调整 TopN 的 N 值&#xff0c;岂不是更方便&#xff1f; 如下示例&#xff1a;图表呈现了各品牌…

centos7上搭建mongodb数据库

1.添加MongoDB的YUM仓库&#xff1a; 打开终端&#xff0c;执行以下命令来添加MongoDB的YUM仓库&#xff1a; sudo vi /etc/yum.repos.d/mongodb-org-4.4.repo 在打开的文件中&#xff0c;输入以下内容&#xff1a; [mongodb-org-4.4] nameMongoDB Repository baseurlh…

【sping】在logback-spring.xml 获取项目名称

在日志文件中我们想根据spring.application.name 创建出的文件夹。 也不想死在XML文件中。 application.yml spring:application:name: my-demo logback-spring.xml <springProperty name"application_name" scope"context" source"spring.app…

如何用微信小程序实现远程控制无人售货柜

如何用微信小程序实现远程控制无人售货柜呢&#xff1f; 本文描述了使用微信小程序调用HTTP接口&#xff0c;实现控制无人售货柜&#xff0c;独立控制售货柜、格子柜的柜门。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规格 序号设备名称厂商1智能WiFi…

Java基础:设计模式之简单工厂模式

简单工厂模式是一种创建型设计模式&#xff0c;它通过一个专门的类&#xff08;即工厂类&#xff09;负责创建对象&#xff0c;从而将对象的创建过程与客户端代码解耦。简单工厂模式的核心在于提供一个统一的入口&#xff0c;接收外界请求并根据请求参数返回相应的对象实例&…

Linux系统上C++使用alsa库播放声音文件

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、命令行1.ffmpeg2.aplay 二、代码实现总结 前言 平常读麦克风的场景居多&#xff0c;有时候也需要播放一个声音文件&#xff0c;这里就介绍怎么处理。 一、…

自动驾驶光学校准反射板

光学校准反射板是一种用于光学系统校准的重要工具。它以其高反射率和精确的几何特性&#xff0c;为光学仪器、光学系统和光学元件的校准提供了可靠的参考。在现代光学领域&#xff0c;光学校准反射板的应用已经深入到各个领域&#xff0c;从科学研究到工业生产&#xff0c;都离…

# IDEA2019 如何打开 Run Dashboard 运行仪表面板

IDEA2019 如何打开 Run Dashboard 运行仪表面板 段子手168 1、依次点击 IDEA 上面工具栏 —> 【View】 视图。 —> 【Tool Windows】 工具。 —> 【Run Dashboard】 运行仪表面板。 2、如果 【Tool Windows 】工具包 没有 【Run Dashboard】 运行仪表面板 项 依次…

慈航医疗“五进”实践活动第九场:范庄村爱心义诊,村民健康有“医”靠

为落实推进“健康中国”战略&#xff0c;提升居民健康意识和预防疾病能力&#xff0c;4月18日&#xff0c;慈航医疗健康前往范庄村开展健康义诊活动&#xff0c;为100余位村民送上了一份暖心的公益关爱。 义诊当天&#xff0c;在志愿服务队队员的引领下&#xff0c;慈航医疗健康…

数据结构|树形结构|并查集

数据结构|并查集 并查集 心有猛虎&#xff0c;细嗅蔷薇。你好朋友&#xff0c;这里是锅巴的C\C学习笔记&#xff0c;常言道&#xff0c;不积跬步无以至千里&#xff0c;希望有朝一日我们积累的滴水可以击穿顽石。 有趣的并查集剧情演绎&#xff1a;【算法与数据结构】—— 并…

JavaScript —— APIs(三)

一、事件流 &#xff08;一&#xff09;定义 &#xff08;二&#xff09;事件捕获 事件捕获&#xff0c;对话框从大到小弹出&#xff0c;先弹出爷爷&#xff0c;最后弹出儿子 &#xff08;三&#xff09;事件冒泡 冒泡事件&#xff0c;对话框从小到大弹出&#xff0c;先弹出…

详解QString与QByteArray使用对比

QString与QByteArray是Qt库中两种不同的字符串/字节序列容器&#xff0c;各自服务于特定的应用场景。本篇文章将详细解析它们的异同&#xff0c;帮助您在实际编程中准确选择和有效地使用这两种类型。 参考 QString类的使用 相同之处 构造与初始化&#xff1a; 两者都支持直接使…

Apache Answer 开源问答社区安装体验

Answer 是由 SegmentFault 思否团队打造的一款问答平台软件,后端使用 Go 语言编写,于2022年10月24日(程序员节)正式开源。你可以免费使用 Answer 高效地搭建一个问答社区,并用于产品技术问答、客户支持、用户交流等场景。 2023年10月9日,Answer 顺利通过投票,以全票通过…

Binlog、Redo 和 Undo 的概念与区别

目录 Binlog&#xff08;Binary Log&#xff09; Redo Log&#xff08;重做日志&#xff09; Undo Log&#xff08;回滚日志&#xff09; Binlog 与 Redo Log 和 Undo Log 的区别 Binlog&#xff08;Binary Log&#xff09; Binlog&#xff0c;即二进制日志&#xff0c;是M…

华为sr-mpls policy配置案例

SR&#xff0d;MPLS POLICY在ensp上面做不了&#xff0c;这是官方上的配置