MySQL分表时机:100w?300w?500w?都对也都不对!

导读

以交友平台用户中心的user表为例,单表数据规模达到千万级别时,你可能会发现使用用户筛选功能查询用户变得非常非常慢,明明查询命中了索引,但是,部分查询还是很慢,这时候,我们就需要考虑拆分这张user表了。

如果此时,我们才去做分表,可能已经太晚了,为什么呢?

我以最典型的应用场景:用户筛选功能,以查询年龄在18到24岁的100位女性用户为例:

在单表的情况下,我们的SQL是这么写的:

SELECT * FROM user WHERE age >= 18 AND age <= 24 AND sex = 0 LIMIT 100
复制代码

但是,拆分user表后,用户记录分散到了多张表,比如,分散到user_1user_2user_3这三张表,此时,要查询满足上面条件的用户,我们的查询过程就变成这样:

  1. 遍历user_1user_3这三张表
  2. 分别从三张表找出满足条件的用户,即执行上面的SQL
  3. 合并这些用户记录
  4. 从合并结果中过滤出前100名用户记录

通过对比,我们会发现分表后的查询过程跟单表相比,变化是比较大的,这势必导致我们不得不修改代码,如果系统内类似的情况很多,那么,可能引发系统较大规模的业务逻辑改动,所以,在系统真正出现数据库性能瓶颈前,必须提前规划分表方案,预留时间去做系统改造。

那么,问题来了,我们到底在单表数据规模达到多少时,做分表是最合适的呢?

在开头我提到分表的原因是因为单表数据规模太大,导致系统功能使用越来越慢,而影响数据库查询性能的因素很多,有并发连接线程数、磁盘IO,锁等等。但是,一条查询语句如果需要通过磁盘IO来获得查询结果,那么,无论是否存在数据库的并发查询请求,磁盘IO的性能瓶颈都会存在。而连接线程和锁导致的的性能问题,一般只有在高并发的场景下才会出现。所以,减少数据查询的磁盘IO,是我们在优化数据库查询性能时,最先需要考虑的。

那么,MySQL又是通过什么方法来减少数据查询的磁盘IO的呢?我们来看下面这张图:

image-20210128202928887.png

这是很典型的应用请求MySQL的示意图,从图中,我们很容易发现,MySQL为了避免查询时都从磁盘读取查询结果,所以,在磁盘和应用之间加了一层内存,尽可能将磁盘数据加载到内存,那么,下次查询请求访问MySQL时,可以从内存中获取查询结果,避免了过多的磁盘IO的读取

所以,通过MySQL对磁盘IO的优化方案,我们可以看出,只要把表中大部分数据缓存在内存中,那么,数据库的查询性能可以大大提升。结合user表来看,只要user表的数据规模可以保证大多数的数据可以加载到内存,那么,就不需要对user表拆分,反之,则需要拆分。

既然MySQL内存的大小决定了表何时拆分,那么,我们就先来看一下MySQL的内存结构吧

内存管理

MySQL的内存结构: image-20210126223939325.png整个MySQL的内存主要分为3部分

Thread Memory:这部分内存空间是每个连接线程独享的,也就是说每个连接自身独立拥有自己的内存空间。连接释放时,

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值