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.mfbz.cn/a/576953.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spark 基础

/* Why Spark一、MapReduce编程模型的局限性1、繁杂:只有Map和Reduce两个操作,复杂的逻辑需要大量的样板代码2、处理效率低:2.1、Map中间结果写磁盘,Reduce写HDFS,多个Map通过HDFS交换数据2.2、任务调度与启动开销大3、…

C++中的queue(容器适配器)

目录 一、成员函数 一、构造函数 二、入栈 push 三、出栈 pop 四、判空 empty 五、队列大小 size 六、取队头元素 front 七、取队尾元素 back 八、入栈 emplace 九、交换函数 swap 二、非成员函数重载 一、关系运算符重载 二、交换函数 swap C中的queue不再是容…

HWOD:单词倒排

一、知识点 此题,笔者自己写的代码中flag的设置极为精妙 二、题目 1、描述 对字符串中的所有单词进行倒排。 说明: (1)、构成单词的字符只有26个大写或小写英文字母; (2)、非构成单词的字符均视为单词间隔符; (3)、要求倒…

Visual Studio 对 C++ 头文件和模块的支持

在 C 编程领域,头文件和模块的管理有时候确实比较令人头疼。但是,有许多工具和功能可以简化此过程,提高效率并减少出错的可能性。下面是我们为 C 头文件和模块提供的几种工具的介绍。 构建明细 通过菜单栏 Build > Run Build Insights&a…

uni-app中配置自定义条件编译

前提:官网提供的自定义编译不满足条件 package.json | uni-app官网 下文:不详细写,主要写关键思路 package.json文件 主要看scripts的执行命令,其他依赖就是用vue-cli方式创建uni-app项目生成的 {"name": "un…

命令行启动pytest自动化程序时,程序卡住不动了,不继续往下执行了

一、问题描述 在执行pytestallure自动化测试工具的时候,命令行启动程序时,程序卡住不继续往下执行,如下图所示。 代码主函数如下: 二、解决方法 测试客户项目时遇到2次此类问题,2次问题原因不一样。 原因一&#xf…

3d合并的模型为什么没有模型---模大狮模型网

在3D建模中,合并模型是常见的操作,它可以将多个模型合并成一个整体。然而,有时候在合并后却发现部分模型消失了,这可能会让人感到困惑和失望。本文将探讨为什么合并的3D模型中会出现没有模型的情况,并提供一些解决方法…

API和微服务设计的优化方式有哪些?

在构建响应迅速、用户体验良好的应用程序中,API性能的优化至关重要。在构建高性能的API时,采取综合策略是至关重要的。通过采用一系列策略,我们可以确保API在处理请求时高效运行,提供流畅的服务。 一、API和微服务设计的优化可以…

Edge下载文件提示无法安全下载的解决方法

问题描述:最近Edge在下载文件时总是提示:无法安全下载,本文记录一下解决方法。 提示截图: 解决方式一: 1. 点击下图红框的三个点,选择保留 2. 选择仍然保留 解决方式二: 第一种方式每下载一次…

MySQL双层游标嵌套循环方法

文章目录 1、需求描述2、思路3、创建存储过程 1、需求描述 1、在项目中,需要将A表中主键id,逐个取出,作为条件,在B表中去逐一查询,将B表查询到的结果集(A表B表关系:一对多)&#xf…

Qt下使用OpenCV截取图像并在QtableWidget表格上显示

文章目录 前言一、在QLabel上显示图片并绘制矩形框二、保存矩形框数据为CSV文件三、保存截取图像四、将截取图像填充到表格五、图形视图框架显示图像六、示例完整代码总结 前言 本文主要讲述了在Qt下使用OpenCV截取绘制的矩形框图像,并将矩形框数据保存为CSV文件&a…

【经验分享】MySQL集群部署一:主从模式

目录 前言一、基本介绍1.1、概念1.2、执行流程 二、部署2.1、通用配置2.2、主节点配置2.3、从节点配置2.4、主从测试2.5、谈一谈主节点历史数据同步问题 前言 MySQL的部署模式常见的包括以下几种: 独立服务器部署主从复制部署高可用性集群(HA&#xff…

Angular创建项目

Angular创建项目 文章目录 Angular创建项目1. 创建项目1.1 直接安装1.2 跳过npm i安装 2. 运行程序 1. 创建项目 ng new 项目名称 1.1 直接安装 ng new angulardemo --同时会安装依赖包,执行的命令就是npm i 1.2 跳过npm i安装 ng new angulardemo --skip-inst…

【数据结构7-2】-二叉排序树(建立、遍历、查找、增加、删除)

目录 1 基础说明2 基本思路-二叉树的创建和插入2.1 节点存储结构的建立2.2 二叉树创建函数的设计2.3 二叉树插入函数的设计2.4 简单的进行二叉树的检测看看插入的对不对:2.5 整体代码: 3 二叉树的遍历3.1 中序遍历3.2 程序代码:3.3 程序结果&…

RFID技术引领3C手机镜头模组产线智能化转型

RFID技术引领3C手机镜头模组产线智能化转型 应用背景 随着智能手机市场的快速发展与技术创新,手机镜头模组作为影像功能的核心组件,其生产精度、效率及供应链管理的重要性日益凸显。面对复杂多变的市场需求、严格的品质要求以及激烈的市场竞争&#xf…

MySQL数据库总结

作者:爱塔居-CSDN博客 专栏:数据库 目录 前言 一、数据库操作 1.1 创建数据库 1.2 显示当前数据库 1.3 使用数据库 1.4 删除数据库 二、表的操作 2.1 查看表结构 2.2 创建表 2.3 删除表 三、表的增删改查操作(CRUD) 3.1 新增 3.…

改ip地址软件手机怎么弄?分享操作指南与注意事项

随着移动互联网的普及,手机已成为我们日常生活中不可或缺的工具。在某些情况下,我们可能需要更改手机的IP地址,以满足特定的网络需求或实现某些功能。然而,对于许多用户来说,如何在手机上更改IP地址可能是一个相对陌生…

clickhouse与oracle传输数据

参考 https://github.com/ClickHouse/clickhouse-jdbc-bridge https://github.com/ClickHouse/clickhouse-jdbc-bridge/blob/master/docker/README.md clickhouse官方提供了一种方式,可以实现clickhouse与oracle之间传输数据,不仅仅是oracle&#xff0…

ShardingSphere 5.x 系列【25】 数据分片原理之 SQL 解析

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 分片执行流程1.1 Simple Push Down1.2 SQL Federation2. SQL 解析2.1 解析…

代码随想录算法训练营DAY38|C++动态规划Part.1|动态规划理论基础、509.斐波那契数、70.爬楼梯、746.使用最小花费爬楼梯

文章目录 动态规划理论基础什么是动态规划动态规划的解题步骤DP数组以及下标的含义递推公式DP数组初始化DP数组遍历顺序打印DP数组动态规划五部曲 动态规划应该如何debug 509.斐波那契数什么是斐波那契数列动态规划五部曲确定dp数组下标以及含义确定递推公式dp数组如何初始化确…