目录

  • 通用的概念
    • 拆分方式
      • 水平拆分(Sharding)
      • 垂直拆分
  • 一、分区
    • 1. 分区的特点
    • 2. 分区路由规则
    • 3. 分区优/缺点
    • 参考
  • 二、分库分表
    • 为什么分库分表
      • 1. 分库
      • 2. 分表
      • 3. 分库分表的数据量判断
    • 中间件
    • 有哪些问题
      • 1. 数据扩缩容方式
        • (1)根据范围range分表
        • (2)根据hash取模
        • (3)一致性hash(这种情况怎么在线迁移数据)
        • 参考
      • 2. 分库分表如何迁移数据(感觉不太好,待完善)
      • 3. 分库后的事务问题
      • 4. 对SQL的影响
        • (1)join问题
        • (2)group by聚合问题
        • (3)order by + limit offset分页问题
      • 5. 分布式ID(待补充细节)
      • 6. 业务查询时没有分表键(待补充)
    • 参考
  • 三、业务场景

通用的概念

拆分方式

水平拆分(Sharding)

解释: 表结构不变,数据分散到多个其他相同结构的表中
优点: 缓解单数据库表的压力,流量按数据分布进行分流。

垂直拆分

解释: 表结构发生改变,一张表的列拆成多张表,每张表的数据行数一样,且保持不变。
优点: 常常按业务拆分,缓解表压力,流量按业务分流。

一、分区

以MySQL为例。在5.1版本之后增加了对分区的支持,常见的存储引擎都支持分区,如InnoDB、MYISAM、NDB等。

1. 分区的特点

  • 分区是在物理上将一张表分割成多张物理分区,但是逻辑上对外还是一张表
  • 支持水平分区,但不支持垂直分区
  • 采用的是局部分区索引的方式,即一个分区对象存放一部分索引,而非全局分区索引方式(所有分区数据对应的索引存放在一个对象中)。因此若是查询未能定位数据在哪个分区,即使走索引也会在每个分区挨个走索引,成本翻多倍。
  • 分区字段可以存在NULL

2. 分区路由规则

  • Range:按连续数值区间分区
  • LIST:按离散数值列表分区
  • HASH:对用户自定义表达式(返回值是自然数)进行分区(求模分区)
  • KEY:支持blob、text以外的字段为分区健

3. 分区优/缺点

如下场景分区表性能好:

  • 删除某分区下的数据时,相比非分区表,不需要查出所有数据再删除,只需要删除分区即可。
  • 查询的数据只存在一个分区内且数据量较大时,性能高。
    • 查询分区表时,根据查询键找到所在分区,全表扫描。
    • 查询非分区表时,要么因为查询数据量大发生全表扫描,要么走索引找到所有符合条件的数据,再回表,整体性能不如分区表的全表扫描

如下场景分区表性能差:

  • 走索引且查询数据量小,查询条件无法判断数据所在分区

    • 查询分区表时,会在所有的分区表进行索引扫描。代价是分区数量*单表IO次数
    • 查询非分区表时,直接查询索引。代价是单表IO次数

其它优缺点:

  • 程序对分区表无感,不需要修改代码
  • 数据分布可能不均匀,性能提升有限
  • 使用RANGE、LIST的分区方式,则需要不断对分区维护。有分区以外的数据时,需要新建分区。

参考

  • mysql表分区详解

二、分库分表

为什么分库分表

1. 分库

  • 数据量过大,单机磁盘不足,需要把数据分散到多台节点上
  • 连接数过多,单机无法支持过多的连接
  • 符合微服务按业务拆分理念

2. 分表

  1. 单表数据量过大,索引层数多,即使走索引性能优化也不是很好

    • 个人猜想:比如单表2亿数据,建立非聚集索引,树高度为4。拆分成10张表后 ,单表2千万,树高度为3,查询一条数据,走索引并回表,IO次数为4*2=8
    • 若分表,假设按查询条件分表。IO次数为1(查找分区)+ 3 * 2 (回表)= 7
    • 若是查询条件里没有分表键,就会在所有表里查询,性能反而下降。
  2. 索引过大,一次无法将全部索引缓存,需要额外进行磁盘IO

  3. 数据插入时重建索引比较耗时

如何计算树的高度以及如何判断一次查询的IO次数

3. 分库分表的数据量判断

阿里巴巴的《Java开发手册》提出:单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。

我个人认为需要计算索引的树高度,超过3层时就要考虑分表了。

中间件

Client模式 Proxy模式
概念 分库分表逻辑在本地控制,直接连接多个数据库,并且将查询结果在本地汇总 独立的服务管理分库,应用连接代理服务。
性能方面 较好。直连数据库 一般,多了层代理转发,并且还要维护一个路由关系表
内存方面 本地数据合并,占用本地的CPU和内存 不额外占用调用者的CPU和内存
架构复杂度 只需要引入jar包,不会有单点故障问题 需要额外部署服务,要考虑高可用,复杂度增加
升级管理 需要单独维护jar包,升级要更改各个服务的依赖版本 对调用者透明,升级维护无感知
中间件 Zebra、Sharding-jdbc、TSharding MyCat、KingShard、Atlas、Cobar

有哪些问题

1. 数据扩缩容方式

(1)根据范围range分表

优点:

  • 扩容方便,直接增加对应的表即可

缺点:

  • 存在热点问题,比如按日期分表,最近一个月的数据都在一张表里,访问量大。而历史数据访问量小

(2)根据hash取模

优点: 不会存在明显的热点问题
缺点: 扩容难,重hash会发生缓存雪崩

如何避免重计算hash并导致所有数据需要迁移(类似缓存雪崩): 可以参考hashmap的扩容方式。节点数为2的幂次,每次扩容节点数翻倍,并且重新计算hash后,只有一部分数据需要迁移到新节点。

(3)一致性hash(这种情况怎么在线迁移数据)

个人认为跟Redis Cluster的槽有点像。都是避免redis节点和数据直接关联,利用槽去绑定数据。

简单原理:

  • 构造一个圆环,圆环上有 2 32 2^{32} 232个槽
  • 对服务器的IP或者名称进行hash,然后用 2 32 2^{32} 232取模,将其映射到圆环的槽位上
  • 将数据的key进行hash并取模,落到圆环的槽位上
  • 圆环上的数据沿着顺时针查找到的第一个服务器,就是所属的服务器。

优点: 扩缩容方便,不会引起缓存雪崩。直接添加或者删除结点后,只会有一部分数据需要迁移
缺点: 可能有数据倾斜造成数据分布不均的问题,可以对机器名称或者ip加编号后进行hash,得到多个虚拟结点。虚拟节点数据越多,均匀分布概率越大。

参考

  • 一致性哈希算法原理详解
  • Redis Cluster为什么选哈希槽不选一致性哈希?

2. 分库分表如何迁移数据(感觉不太好,待完善)

停机迁移比较简单,建好新的分区表后直接将数据插过去就可以,然后修改代码读取表。这里主要描述下在线迁移。

数据双写:

  1. 代码层面,开启新旧表双写,并编写代理层能够控制在线切换读取的表。发布服务在线升级。
  2. 记录新表增量字段起始值,将旧表中小于该值的数据迁移到新表中
    • 推荐增量字段为 有序主键>唯一索引键>非唯一索引键
    • 唯一键好处理,非唯一键还需要将等于新表起始值的数据迁移过来(发生主键冲突的数据则不需要迁移)

异步监听: (没写清楚)
监听binlog,将数据迁移到新表上

3. 分库后的事务问题

需要分布式事务。不过分布式事务本身会带来额外的损耗,所以设计时应当尽量避免。

分布式事务见:分布式理论与Seata

4. 对SQL的影响

(1)join问题

跨库:

  1. 字段冗余,避免关联
  2. 若关联全局表,可以在所有库中冗余一份相同的全局表,避免跨结点
  3. 代码层面关联
  4. 借助ETL工具,定时关联汇聚,生成新的关联好的表
  5. 判断关联关系,将能够关联上的数据放到一个分片上。

同库分表后关联:

待办

(2)group by聚合问题

各节点得到结果后,程序端合并

(3)order by + limit offset分页问题

业务上禁止跳页,只允许上一页下一页:

  • 根据主键排序的话,每次分页需要记录上次查询结果最后一条数据的主键。查询下一页数据(比如一页十条),需要在所有分表执行select xxx from table where id > xx limit 10 。然后在程序端合并,得到最小的10条数据。
  • 根据唯一索引列排序时,方法同主键排序
  • 根据非唯一索引列排序时,应该在这个基础上按主键排序。即 order by 非唯一索引列,主键 。这时要记录上次查询结果最后一条数据的非唯一索引列和主键

允许跳页:

一次返回数据较多,不推荐

比如查询第二页数据。需要返回所有表的前两页数据,在程序中合并计算第二页数据是哪些。页数越远,需要处理的数据越多,网络开销、CPU性能都会占用较大。

5. 分布式ID(待补充细节)

优点 缺点
uuid 实现简单 连续性差,作为主键每次新增数据都会触发索引重建。
分布式环境中可能重复
雪花算法 性能好,有序 依赖服务器时间,时钟回拨可能生成重复ID
号段模式
redis/zookeeper Redis基于INCR 命令生成 分布式全局唯一id
zookeeper一种通过节点,一种通过节点的版本号

6. 业务查询时没有分表键(待补充)

详解分库分表后非分片键如何查询

参考

  • 关于分库分表
  • 数据库分区、分表、分库、分片
  • 分库分表-理论、方案、问题总结
  • 分库分表经典15连问
  • MySQL:互联网公司常用分库分表方案汇总

三、业务场景

  • 用户操作日志:分表

【数据库】分库分表分区相关推荐

  1. 数据库 分库 分表 分区

    我们知道,如果我们使用mysql,当数据库数据量达到一定数据量之后,会考虑对数据库进行分库分表等操作,但是在什么情况下做怎么的切分,下面分表介绍. 一.分库 1 分库原因 首先,在单台数据库服务器性能 ...

  2. 数据库分库分表(sharding)系列(五) 一种支持自由规划无须数据迁移和修改路由代码的Sharding扩容方案...

    为什么80%的码农都做不了架构师?>>>    版权声明:本文由本人撰写并发表于2012年9月份的<程序员>杂志,原文题目<一种支持自由规划的Sharding扩容方 ...

  3. MariaDB Spider 数据库分库分表实践 分库分表

    分库分表 一般来说,数据库分库分表,有以下做法: 按哈希分片:根据一条数据的标识计算哈希值,将其分配到特定的数据库引擎中: 按范围分片:根据一条数据的标识(一般是值),将其分配到特定的数据库引擎中: ...

  4. 数据库--分库分表--垂直分表与水平分表

    原文网址:数据库--分库分表--垂直分表与水平分表_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍数据库的分库分表的方案:垂直分表与水平分表. 关系型数据库本身比较容易成为系统瓶颈,单机存储容 ...

  5. 数据库分库分表解决方案

    数据库分库分表解决方案 前言 MySQL表大小限制 分表方案 垂直分表 水平分表 按月分表 MySQL分区表 分库方案 按业务分库 按表分库 拆分后的问题及常见的解决方案 垂直拆分 跨库Join问题 ...

  6. 数据库分库分表中间件对比(很全)

    数据库(分库分表)中间件对比 分区:对业务透明,分区只不过把存放数据的文件分成了许多小块,例如mysql中的一张表对应三个文件.MYD,MYI,frm. 根据一定的规则把数据文件(MYD)和索引文件( ...

  7. 亿级流量网站架构核心技术之“数据库分库分表策略”

    本文节选自<亿级流量网站架构核心技术--跟开涛学搭建高可用高并发系统>一书 张开涛 著 电子工业出版社出版 小编会从留言中选择获赞最多的前五名用户免费送出此书哦!规则见文末. 数据库分库分 ...

  8. 一文搞懂MySQL数据库分库分表

    如果数据量过大,大家一般会分库分表.分库需要注意的内容比较少,但分表需要注意的内容就多了. 工作这几年没遇过数据量特别大的业务,那些过亿的数据,因为索引设置合理,单表性能没有影响,所以实战中一直没用过 ...

  9. mysql 分库分表分区总结

    Mysql目录结构 一个库一个目录 MyISAM引擎 InnoDB引擎 分库分表分区总结 对于分区分表 都可以进行横向(按表字段分),纵向分(按数据行分),此文暂时值考虑横向分. 对于分库:分库 分区 ...

  10. 数据库分库分表(sharding)系列

    数据库分库分表(sharding)系列 转载于:https://www.cnblogs.com/gotodsp/p/6517478.html

最新文章

  1. linux进程间通信:POSIX 共享内存
  2. python 测试 多线程 _thread和threading模块 线程同步,线程优先级队列
  3. jzoj100046-收集卡片【暴力】
  4. php语句过滤掉html标签_php过滤html标签
  5. oracle 解死锁权限,讲解Oracle数据库中结束死锁进程的一般方法
  6. HDZ城市行深圳站|AIoT时代,如何抓住智联生活的战略机会点?
  7. 手把手教你部署Nagios
  8. 第三天.SQL语言基础
  9. linux jmeter 内存,怎么在Linux下改变JMeter内存
  10. datatable自定义表单或者导出excel按钮,搜索
  11. 计算机网络—4运输层(TCP连接管理、流量控制、拥塞控制)
  12. 一种数字全息散斑干涉测量仿真模拟系统
  13. UEditor(四)——表情包
  14. C语言哈希表uthash的使用方法详解(附下载链接)
  15. ​LeetCode刷题实战592:分数加减运算
  16. java-获取上个月的第一天和最后一天
  17. 使用svn报错之An error occurred while contacting the repository
  18. Java源码:Reference与ReferenceQueue
  19. 让打工人颤抖的监控系统:离职倾向、摸鱼通通都能被监测!你还敢上班摸鱼吗?...
  20. 学生成绩管理分析系统的设计与实现(论文+源码)_kaic

热门文章

  1. 特征提取邻域大小受限_您可以通过拖动装订线来更改两个邻域的大小
  2. python把txt大小写英文字母等删掉
  3. Flood-Fill算法
  4. 前端 + 后端 实现分片上传(断点续传/极速秒传)
  5. DHCP+故障转移+WINS
  6. 基于51单片机的计算器 汇编语言 proteus仿真 数码管显示
  7. P4158 [SCOI2009]粉刷匠(dp)
  8. Excel更改超级链接图片打开方式
  9. 关于android手机
  10. SONiC架构DOCKER组件交互分析