深入浅出mysql分库分表

文章目录

    • 为什么要分库分表?
    • 什么场景下才需要分库分表?
      • [1. 数据量增长导致数据量过大--分表](#1. 数据量增长导致数据量过大--分表)
      • [2. 高并发访问--分库](#2. 高并发访问--分库)
      • [3. 地理分散的业务--分库](#3. 地理分散的业务--分库)
    • 分库分表的区别
      • [分库(Database Sharding)](#分库(Database Sharding))
      • [分表(Table Partitioning)](#分表(Table Partitioning))
    • 垂直拆分、水平拆分的区别
      • [垂直拆分(Vertical Partitioning)](#垂直拆分(Vertical Partitioning))
      • [水平拆分(Horizontal Partitioning)](#水平拆分(Horizontal Partitioning))
    • 浅谈

分库分表也是一个老生常谈的问题,很多人都习惯把分库分表放在嘴边,来显得高大上,其实我对于这点是非常不赞同的。先说明关键点:" 非必要绝对不要进行分库分表 "

为什么要分库分表?

很多人总是第一反应说因为高并发,其实这个回答是非常不严谨的。我见过非常多的高并发系统都是单库单服务,照样跑的很稳定。其实分库分表的核心是**《数据库面临了性能瓶颈》**

所以分库分表是只有在数据库的性能处理能力确实满足不了当前情况,且已经很难靠业务进一步提升后,才采取的必要措施,如果性能满足的情况下,非必要绝对不要进行分库分表

因为分库分表一定会带来额外的复杂性和挑战,带来的成本也是巨大的

  1. 增加复杂性:开发者需要处理数据的分片逻辑、路由请求到正确的数据库实例等,这增加了开发和维护的难度
  2. 数据一致性问题:在分布式数据库环境中,保持数据的一致性是一个挑战。跨多个数据库实例的事务处理更加复杂,可能导致数据不一致的风险
  3. 事务管理困难:传统的数据库事务(ACID属性)在分库分表后变得难以实现。跨多个数据库的事务需要额外的协调机制,这可能影响性能
  4. 查询性能下降:虽然分库分表可以提高单个数据库的性能,但跨多个数据库的查询可能需要更多的协调和数据聚合,这可能导致整体查询性能下降
  5. 数据迁移和同步问题:数据迁移到新的分库分表架构可能非常复杂和耗时。此外,保持数据在多个数据库之间的同步也是一个持续的挑战
  6. 增加运维成本 :管理多个数据库实例需要更多的运维工作,包括监控、备份、故障恢复等,这会增加运维成本
    虽然当前分库分表的技术已经相当成熟了,但是对于这个最终的选择仍然需要慎重

什么场景下才需要分库分表?

1. 数据量增长导致数据量过大--分表

这个应该很好理解,就是单表的存储的数据量超过一定的阈值,比如可能单表数据1000W条,或者可能占用了3-4G的磁盘,这个时候sql查询的性能会明显的下降,并且这个时候通过优化索引也没有办法很好的解决的情况下,这个时候就可以考虑用分表的方式将数据分散到多个表里面

这里通常采取的是横向拆分

这里的核心其实就是因为数据量的增多,导致B+树层数的增加,导致IO增加,引起性能下降。其实单表最多能记录多少条数据而不卡这个跟单条数据的大小也是有很大的关系的,具体业务具体分析,记住技术是为业务服务的,业务也倡导技术的发展

但是这里在最终确定选择这个方案前,可能还有其他考量,比如确定大量数据的原因,历史数据是否一定需要保存(比如起一个定时任务每天定时清理三个月前的数据)?是否可以直接删除或者存档es等来缓解单表数据量的压力,如果可以当然也没必要分表

2. 高并发访问--分库

单库的访问量过高,导致数据库压力过大,也是一个核心问题。这个可能也跟数据库机器的性能相关,对于机器好的服务来说,可能抗压能力更强,但是如果再高点比如7-8k qps,数据库的稳定性也面临着相当大的压力。这个时候就不是分表的问题了,这里应该是采用分库的方式,通过增加数据库的方式将访问的压力分散到多个数据库实例中,来提高整体的并发处理能力

一般的分库都是搭配微服务架构,常见的做法是根据业务的归属拆分不同的库,将不同的表拆分到不同的库中以达到专库专用,在降低风险的同时也减低了耦合度

3. 地理分散的业务--分库

这个比较少见,业务覆盖多个地区或国家,需要在不同地理位置提供服务,然后在地区本地部署服务以减少时延,或者某些地区的数据保护法规要求数据必须存储在本地等等,这里就不做扩充

分库分表的区别

分库(Database Sharding)

定义: 分库是指将数据分布到多个数据库实例中,每个实例可以是独立的数据库服务器或者集群。通常用于处理跨多个业务模块的大规模数据,适用于业务模块之间相对独立的场景
特点:

  • 每个数据库实例存储的数据是独立的,互不干扰
  • 可以针对不同的业务模块或数据类型进行分库
  • 通常用于解决单一数据库实例无法承载的数据量或并发请求量问题。

适用场景:

  • 业务模块之间关联性不大,可以独立存储和管理
  • 数据量或访问量非常大,单一数据库无法满足性能需求
  • 需要根据业务模块进行物理隔离,例如出于安全或合规性考虑

分表(Table Partitioning)

定义: 分表是指将单个表中的数据分割成多个子表,这些子表可以分布在同一个数据库实例中,也可以分布在不同的实例中。
特点:

  • 子表之间在逻辑上是连续的,但在物理上是独立的
  • 通常基于某种键值(如时间戳、ID范围)进行数据分割
  • 可以提高查询和更新的性能,尤其是在处理大量数据的表时

适用场景:

  • 表中的数据量非常大,单一表的维护和查询效率低下
  • 需要对数据进行逻辑上的分组,例如按照时间范围存储日志数据
  • 希望简化数据管理,例如通过分表来实现数据的自动归档和清理

垂直拆分、水平拆分的区别

垂直拆分(Vertical Partitioning)

定义: 垂直拆分是指根据数据表的列来拆分数据,将一个表中不常用的列或业务逻辑上相对独立的列拆分到不同的表或数据库中。垂直拆分是按列进行的,关注的是表的宽度。这个一般很少在系统后续优化中使用,除非是大规模的重构,一般会在数据库设计的初期就考虑好相关的问题。举例假设拆分一张用户表,将用户工号,用户名等关键字段放在主表,将性别,学历等其它字段放到子表,这样其实业务中用到这些字段的地方都需要修改,成本也是很高的
特点:

  • 减少了表的宽度,每个表只包含一部分列
  • 可以提高查询性能,因为查询时只需要访问相关的列
  • 有助于业务逻辑的分离,使数据库更加模块化

适用场景:

  • 当表中包含大量列,但查询通常只访问其中一小部分列时
  • 需要根据业务逻辑对数据进行分离,例如将用户信息和交易记录分开存储

水平拆分(Horizontal Partitioning)

定义: 水平拆分是指根据数据表的行来拆分数据,将数据按照某种规则(如范围、哈希等)分割到不同的表或数据库中。水平拆分是按行进行的,关注的是表的长度。水平拆分可以减少单表的数据量,提高查询和更新的性能,有助于根据数据的属性进行逻辑分组
特点:

  • 减少了单表的数据量,有助于提高单表的查询和更新性能
  • 需要考虑数据分片键的选择,以确保数据均衡分布
  • 可能需要跨多个表或数据库进行查询,增加了查询的复杂性

适用场景:

  • 当表中的数据量非常大,单一表难以有效管理时
  • 需要根据数据的某个属性(如时间、地区、用户ID)进行逻辑分组

浅谈

现在发展的很快,其实大部分的情况下,服务器的资源都是过剩的,就导致大部分的公司项目团队和开发根本不关心sql的性能问题,本着快速做完能跑就行去开发代码,或者直接干脆以空间换时间,采用高性能的机器扩容等即可。我见过太多的开发的sql非常浪费,优化空间巨大

相关推荐
靖顺1 小时前
【OceanBase 诊断调优】—— packet fly cost too much time 的根因分析
数据库·oceanbase
liuxin334455661 小时前
学籍管理系统:实现教育管理现代化
java·开发语言·前端·数据库·安全
yuanbenshidiaos3 小时前
C++--------------树
java·数据库·c++
dengjiayue5 小时前
MySQL 查询大偏移量(LIMIT)问题分析
数据库·mysql
言之。5 小时前
【MySQL】在MySQL中如何定位慢查询?
数据库·mysql
DashVector5 小时前
如何通过HTTP API插入Doc
数据库·人工智能·http·阿里云·向量检索
DashVector5 小时前
如何通过HTTP API分组检索Doc
服务器·数据库·http·数据库开发·数据库架构
Suwg2095 小时前
【MySQL】踩坑笔记——保存带有换行符等特殊字符的数据,需要进行转义保存
数据库·笔记·mysql
PittDing5 小时前
【更新】Docker新手入门教程2:在Windows系统通过compose创建多个mysql镜像并配置应用
windows·mysql·docker
2401_857610035 小时前
中文学习系统:成本效益分析与系统优化
java·数据库·学习·架构