伪命题之MYSQL分库分表

看到使用分库分表来解决性能问题的时候心里总是不能太理解。

如果同事发生大量请求的时候,损害性能的是硬盘的随机读。那么分库分表也没有对性能的瓶颈进行“分治”啊。

应该的做法是使用一块新的硬盘来创建分库。但是基本的文章都没有提到这点。而且基本上也不会有公司这么做,毕竟现在一快硬盘在1T所有,一个数据库肯定占用不了这么多地方。而且程序员在申请数据库的时候,也没有办法说明使用不同的硬盘来部署这数据库。而且也不知道部署在这些硬盘上有没有大量的随机读。

还有好多人都觉得MYSQL数据库有性能问题,在单表超过500W或者2000W的时候就要分库分表。我觉得从MYSQL的数据结构来说,应该不存在这些问题。(好多帖子说是避免树高过高。)其实树高增加一层会增加一个数量级的数据存放量。如果通过分库分表来减少树高,可以累死程序员。这也不是程序员应该考虑的。MYSQL只要缓存一个顶级节点pageCache就相当于做了“分库分表”了。所以一直认为分库分表是个伪命题。

下面使用程序来做一下实验来证明自己的想法。

在测试环境Linux系统下安装mysql 5.7.41。本地使用java 8 为客户端代码。

实验一:单表操作

1)创建数据库test

2)创建T_PERSON表

3)使用Java JDBC 批量插入100,000,000条数据,4096为一个批次。总共耗时为:2150秒

实验二:分表不分库

  1. 创建数据库T_PERSON_1, T_PERSON_2, T_PERSON_3, T_PERSON_4, T_PERSON_5, T_PERSON_6, T_PERSON_7, T_PERSON_8.
  2. 使用java JDBC批量插入100,000,000条数据,4096*8为一个批次。每张表总共12,500,000条数据(小于2000W条)。总共耗时为:2015秒。

实验三:分库分表

  1. 创建数据库Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8
  2. 每个库创建T_PERSON表
  3. 使用java JDBC批量插入100,000,000条数据,4096*8为一个批次。每张表总共12,500,000条数据(小于2000W条)。总共耗时为:2022秒。跟实验二不同的是实验三使用了3个Connection。因为是使用了三个数据库,没有办法使用相同的connection去插入。

数据库

表大小

连接数

Batch

总共插入数据

耗时时间(秒)

实验1

1

1

8.4G

1

4096

100,000,000

2150

实验2

1

8

1.1G

1

4096

100,000,000

实验3

8

1

1.1G

8

4096

100,000,000

实验1

Postgre

1

1

NA

1

4096

100,000,000

读取实验

客户端环境,java8, spring-boot 2.6.6, sharing-sphere 3.1.0

实验一:使用上诉实验一的环境。共使用16个Connection。使用jmeter进行压力测试10 Thread,QPS 为826, 20 thread 889.

实验二:10 thread 833, 20 thread 944

实验三:10 thread 848, 20 thread 902

数据库

连接数

10 threads

20 threads

实验1

1

1

16

826

889

实验2

1

8

16

833

944

实验3

8

1

2

848

902

跟预想的是一样的,分库分表并不能提高性能。

读取实验二

客户端环境,java8,使用多线程,JDBC来测试性能。

数据库

连接数

测试结果

测试结果

实验1

1

1

8

5304.73

6086.77

实验2

1

8

8

7140.63

6467.98

实验3

8

1

8

5832.50

6614.85

实验1

1

1

16

14096.30

13497.41

实验1

1

1

24

18694.14

17823.77

实验1

1

1

32

19104.83

21274.47

也证明了分库分表不能明显提高性能,但是增加并发数可以有效的提高性能。因为mysql没有reactive的driver,就没有测试。

PS: 里面涉及大大量的取余的计算,我特意把除数都设置成2的几次幂,我以为编译器会可以帮我优化。但是查看class代码并没有进行优化。

然后又使用javac –O 测试,已经没有进行优化,不知道为什么。

问了一下ChatGPT,他就可以做出优化的解释。

也使用了一下https://www.cnblogs.com/BetterCallSaul/p/MySQL.html​​​​​​ 提到的查看树高的方法。我的数据库使用的10W的时候是2层,但是到了20W就是3层了,1亿的时候也是三层。

ps: innodb_page_size    16384 (16K)

数据量

树高

100000

2

200000

3

300000

3

100000000

3

PS: 该文章是针对网上一些MYSQL性能不好,或者单表500W或者2000W需要进行分表。或者是为了减少树高的一些观念的看法。我觉得这些观点并不应该成为分库分表的主要目的。

摘自《阿里的开发手册》 。

Mysql单表最大记录是多少_mysql单表数据量_怎么又有bug单的博客-CSDN博客mysql单表最大记录数不能超过多少?https://blog.csdn.net/GBS20200720/article/details/125344782

分库分表的目的from ChatGPT

分库分表是一种常见的数据库水平扩展方案,它的主要目的是解决单一数据库的性能瓶颈和容量限制问题,提高系统的扩展性和可用性。

在单一数据库中,当数据量增长到一定程度时,会面临性能瓶颈和容量限制的问题。而分库分表可以将数据水平拆分到多个数据库或数据表中,每个数据库或数据表只负责一部分数据的存储和查询,从而提高了数据库的性能和容量。同时,分库分表也可以增加系统的可用性,当一个数据库或数据表出现故障时,只会影响到一部分数据,其他数据库或数据表仍然可以继续工作,从而保证了系统的正常运行。

除了提高系统性能和容量,分库分表还可以提高数据库的可扩展性。随着数据量的增长,可以通过增加数据库或数据表的数量来扩展系统的容量和性能,而不需要对原有的数据库或数据表进行修改或扩展。

总之,分库分表是一种解决单一数据库性能瓶颈和容量限制问题,提高系统可用性和可扩展性的有效方式。但是,在实际使用中需要考虑数据一致性、查询路由、数据迁移等问题,需要谨慎设计和实施。

我还是觉得chat GPT的答案挺好的。分库分表肯定有用处,但是我们在使用的时候需要评价我们的场景,以及带来的优缺点,然后我们需要权衡这些优缺点。不要一味的听说要分库分表,或者觉得“分库分表” 很高级。

你可能感兴趣的:(mysql,数据库,java)