首页 > 资讯 > 科技 > 正文
2024-03-04 10:15

MySQL处理大数据表的三种解决方案。 写得真好。 我建议收藏它! !

这是一个可能对您有用的社区

一对一沟通/面试手册/简历优化/求职问题,欢迎加入“知识星球”。 以下是提供的部分信息:

这是一个开源项目,可能对您有用

国内Star是一个10万+的开源项目。 前端包括管理后端+微信小程序,后端支持单体和微服务架构。

功能涵盖RBAC权限、SaaS多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、CRM等功能:

【国内首批】支持JDK 21+ 3.2.0、JDK 8 + Boot 2.7.18双版本

当我们业务数据库表中的数据越来越多的时候,如果你我也遇到过下面类似的场景,那么让我们一起来解决这个问题

基于Boot+Plus+Vue实现的后台管理系统+用户小程序,支持RBAC动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

我们可以从表容量/磁盘空间/实例容量三个方面来评估数据量。 我们分别来看一下。

表容量主要从表的记录数、平均长度、增长、读写量、总大小来评估。 一般来说,对于OLTP表,建议单表不超过2000万行数据,总大小在15G以内。 访问量:单表读写量在1600/s以内

如何查询行数据:我们在查询表中有多少数据时一般使用的经典SQL语句如下:

select count(*) from table
select count(1from table

但是当数据量太大时,这样的查询可能会超时,所以我们需要改变查询方式。

use 库名
show table status like '表名' ; 
或:show table status like '表名'\G ;

上述方法不仅可以查询表的数据,还可以输出表的详细信息。 添加\G格式化输出。包括表名、存储引擎版本、行数、每行字节数等,大家可以自己尝试一下。

查看指定数据库容量

select
table_schema as '数据库',
table_name as '表名',
table_rows as '记录数',
truncate(data_length/1024/10242as '数据容量(MB)',
truncate(index_length/1024/10242as '索引容量(MB)'
from information_schema.tables
order by data_length desc, index_length desc;

查询单个数据库所有表的磁盘使用情况

select
table_schema as '数据库',
table_name as '表名',
table_rows as '记录数',
truncate(data_length/1024/10242as '数据容量(MB)',
truncate(index_length/1024/10242as '索引容量(MB)'
from information_schema.tables
where table_schema='mysql'
order by data_length desc, index_length desc;

查询结果如下:

建议数据量占磁盘使用量的70%以下。 同时,对于一些增长较快的数据,可以考虑使用大的慢速磁盘进行数据归档(归档可参考方案3)

MySQL是基于线程的服务模型。 因此,在一些高并发的场景下,单实例无法充分利用服务器的CPU资源,吞吐量会卡在mysql层。 您可以根据业务考虑适合自己的实例模式。

基于Cloud++Nacos++Vue实现的后台管理系统+用户小程序&支持RBAC动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

我们已经在上面找到了数据表的大小。 那么单表数据量越大,业务执行效率越慢的根本原因是什么呢?

当表的数据量达到千万、上亿的时候,添加索引的效果就不那么明显了。 性能变差的原因是因为维护索引的B+树结构层次变高了。 当查询一条数据时,需要经历更多的磁盘IO,因此查询性能变慢。

你还记得一棵B+树可以存储多少数据吗?

存储引擎的最小存储单元是页,页大小为16k。

B+树的叶子存储数据,内部节点存储键值+指针。 索引组织表通过非叶子节点和指针的二分查找方法确定数据在哪一页,然后去数据页查找需要的数据;

假设B+树的高度为2,即有一个根节点和若干个叶子节点。 这棵B+树中存储的记录总数=根节点指针的数量*单个叶子节点记录的行数。

因此,一棵高度为2的B+树可以存储1170 * 16 = 18720条这样的数据记录。 同理,一棵高度为3的B+树可以存储1170*1170*16=,这意味着它可以存储大约2000万条记录。 B+树高度一般为1-3层,可以满足千万级数据的存储需求。

如果B+树想要存储更多的数据,树结构层次就会更高。 当查询一条数据时,需要经历更多的磁盘IO,因此查询性能会变慢。

知道根本原因后,我们需要考虑如何优化数据库来解决问题

这里提供了数据表分区、分库分表、冷热数据归档三种解决方案。 了解这些解决方案后,您可以选择适合您业务的解决方案。

为什么需要分区:表分区可以查询区间内对应的数据,缩小查询范围,而索引分区可以进一步提高命中率,提高查询效率。 分区是指将一张表的数据按照条件分布到不同的文件中。 没有分区以前是存储在一个文件中,但仍然指向同一张表,只是将数据分散到不同的文件中。

我们先来看看分区的优缺点:

表分区有什么好处?表分区的局限性

在分区之前,可以通过以下方法检查数据库表是否支持分区。

mysql> show variables like '%partition%';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| have_partitioning | YES   |
+-------------------+-------+
1 row in set (0.00 sec)

为什么要分表:分表后,很明显单表的数据量减少了,树的高度变低了,查询所经历的磁盘IO变少了,可以提高效率。 MySQL表拆分分为两种:水平拆分和垂直拆分。

分库分表是为了解决数据量过大导致数据库性能下降的问题。 将原来独立的数据库拆分为多个数据库,将大数据表拆分为多个数据表,从而使单个数据库、单个数据表的数据量变得更小,从而达到提高数据库性能的目的。

定义:数据表行的分割。 通俗地说,就是将数据按照一定的规则拆分到多个表或者多个库中进行存储。 分为库内分表和分库。

比如一张表有4000万条数据,查询速度很慢。 可以分为四个表,每个表有1000万条数据。

定义:列拆分,根据表之间的相关性进行拆分。 常见的情况是一张表将不常用字段和常用字段分开,然后用主键关联起来。或者数据库中有一张订单表和一张用户表。 数据量非常大。 垂直拆分用户库存用户表的数据,和订单库存订单表的数据。

缺点:垂直分离的缺点很明显。 数据不在一张表中,这会增加join或union等操作。

mysql索引效率变差_mysql索引效率_索引查询效率

了解了这两个知识后,我们再来看看分库分表的方案。

1.建模方案:

在分割之前,估计数据量。 比如user表有4000万条数据,现在需要将数据分为4张表user1 user2 uesr3 user4。

例如id=17,17模4加1,所以这条数据就存放在user2表中。

注意:水平分割后的表必须去掉自动增量。 此时的ID可以通过使用ID自增临时表,或者使用redis incr方法来获取。

优点:数据均匀分布到各个表中,出现热点问题的概率很低。

缺点:未来数据扩展和迁移困难。 当数据量增加时,之前分成4张表,现在会分成8张表。 模值会发生变化,需要重新迁移数据。

2.范围范围计划

按范围拆分数据是指将一定范围内的订单存储在某个表中。 例如,user1表中存储id=12,user2表中存储id=1300万。

优点:有利于未来数据扩展

缺点:如果一张表存在热点数据,那么压力就在一张表,其他表没有压力。

我们看到,上述两种解决方案各有缺点,但却是互补的。 那么如果我们将这两种解决方案结合起来会发生什么呢?

3.哈希模数和范围方案的结合

如下图所示,我们可以看到group组存储了ID从0到4000万的数据,然后就有了三个数据库:DB0、DB1、DB2。 DB0 中有 4 个数据库,DB1 和 DB2 中有 3 个数据库。

如果id是15000,那么取模10(为什么取模10,因为有10张表),取0落到DB_0里面,然后根据范围落到里面。

总结:将哈希取模和范围方案结合起来,不仅可以避免热数据的问题,也方便以后的数据扩展。

我们已经了解了mysql的分区和分表。 我们来看看这两种技术的区别以及适用场景。

1、分表的方式有很多种。 使用merge来分表是最简单的方法。 这种方法与根分区的难度差不多,并且对程序代码是透明的。 如果使用其他表分区方式,会比分区更麻烦。

2、分区的实现比较简单。 创建分区表和建普通表没有区别,对代码端透明。

1、可以提高mysql的性能,在高并发情况下有良好的性能。

2、表细分和分区并不矛盾,可以相互配合。 对于那些访问量大、表数据量大的表,对于访问量小但表数据量大的表,我们可以结合表细分和分区。 ,我们可以采用划分方法等。

进行数据库和表分区后,由于数据存储在不同的库中,数据库事务管理变得困难。 如果依赖数据库本身的分布式事务管理功能来执行事务,将会付出很高的性能代价; 如果应用程序辅助控制,形成程序逻辑事务,也会造成编程负担。

进行分库分表后,难免原本逻辑上高度相关的数据会被分成不同的表、不同的库。 这时表的关联操作就会受到限制,无法将不同分库的数据进行Join。 不同表粒度的表无法连接。 这样一来,一次查询就能完成的业务,可能需要多次查询才能完成。

最明显的额外数据管理负担是数据定位问题以及数据增删改查的重复执行。 这些可以通过应用程序来解决,但不可避免地会产生额外的逻辑运算。

例如,对于一个记录用户评分的用户数据表,业务需要找到100个最好的评分。 分表前只能做1条order by语句,分表后就需要n条了。 通过order by语句,分别找到每个子表的前100名用户数据,然后将这些数据合并计算得到结果。

为什么需要冷热归档:其实原因和第二种方案类似,就是减少单表数据量,树的高度变低,查询所经历的磁盘IO减少,可以提高效率。 如果你的业务数据有明显的冷热区分,例如:只需要显示过去一周或一个月的数据。 这种情况下,本周和一个月的数据称为热数据,其余数据为冷数据。 然后我们可以将冷数据归档到其他数据库表中,以提高我们热数据的运行效率。

创建归档表。 原则上,创建的归档表必须与原表一致。

归档表数据的初始化

业务增量数据处理流程

数据采集​​过程

您可以根据您的业务场景选择适合您业务的解决方案。 我给你一些想法~

那么到这里,我要讲的就差不多结束了。 如果有什么不对的地方或者有什么疑问,请大家多多指教!

欢迎加入我的知识星球,全面提升你的技术能力。

如需加入,请“长按”或“扫描”下面的二维码:

的内容包括:实际项目实践、面试招聘、源码分析、学习路线。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)