分表与分库

前言

  当我们的数据量逐渐膨胀,一张表的数据量变得非常巨大以致于影响性能时,我们需要一种手段来将表拆分成若干表以提高性能,这就是分表。当我们的数据量继续膨胀,我们单机数据库中已经存在非常多的子表,并且数据库服务器承受不了这样大量的请求时,我们需要一种手段将单机数据库的压力分摊到若干数据库,这就是分库。

一、简介

  分表:将一张表按照一定的规则划分成若干分表,查询分表时可按照规则直接定位到一张分表,提高查询效率。
  分库:分表之后,一个数据库中会产生非常多的表,数据库中的表过多会影响数据库的性能,并且数据量大了之后一台服务器是无法满足应用的需求,所以需要按照一定规则划分将数据库,将符合规则的表迁移至对于数据库。
  分库分表可分为水平拆分和垂直拆分,水平拆分是按行拆分,将不同行放在不同表中;垂直拆分是按列拆分,将不同列放在不同表中。可以发现分区与分表相似。其实他们的思想相似,但是实际应用的场景不同导致了其实现不同。

ps:数据库表数量过多影响数据库性能的原因如下:
table_definition_cache是表定义信息缓存,用来存放表定义信息.当我们的MySQL中使用了较多的表的时候,缓存需要频繁的切换影响性能.注意,这里设置的是可以缓存的表定义信息的数目,而不是内存空间的大小.
table_open_cache是打开表的缓存数量,不是定义内存的大小,而是定义可以缓存多少打开的表的文件句柄信息.如果定义的太小,那么MySQL在需要打开新表的时候就要不断的关闭已经打开的表和打开此次需要打开的表,性能会受到影响.

二、方式

1. 垂直分表
  也就是“大表拆小表”,基于列字段进行的。一般是表中的字段较多,将不常用的, 数据较大,长度较长(比如text类型字段)的拆分到“扩展表“。一般是针对那种几百列的大表,也避免查询时,数据量太大造成的“跨页”问题。在数据量继续膨胀之后,依然会带来单表数据量过大影响性能问题。
2. 垂直分库
  垂直分库针对的是一个系统中的不同业务进行拆分,拆分之后可以将数据库放在不同的服务器上,以获得更高的处理能力。垂直拆分在一定程度上可以提升硬件资源带来的瓶颈,这种实现方式简单,架构复杂度不高,但是如果数据继续膨胀,导致数据库中表增多,依然会导致性能下降。
3. 水平分表
  针对数据量巨大的单张表(比如订单表),按照某种规则,切分到多张表里面去。 但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈。
4. 水平分库
  针对于数据量巨大的数据库,按照某种规则,切分为多个数据库,切分后的数据库结构一样,放在不同的服务器上,数据根据切分的规则存入对于的数据库,获得了更多的硬件资源。

三、分库分表的一般思路

  分库分表最重要的是拆分键的选择,当我们使用拆分键进行查询时,可以快速定位到对应的数据表,优秀的拆分键可以让查询效率大幅度提升,而差的分区键会导致查询效率反而下降。
1. 单拆分键

  顾名思义,分库分表按照一个键进行拆分,但是有时候我们不使用拆分键进行查找的时候,会将所有表进行扫描,效率低下。有两种解决方案:冗余全量表和冗余关系表。
冗余全量表
  例如将一张订单表t_order拆分成三张表t_order、t_user_order、t_merchant_order。分别使用三个独立的sharding column,即order_id,user_id,merchant_code。每一张表都是全量数据,数据同步可以使用binlog。
冗余关系表
  只有一张表是全量表,其他表是关系表,例如将一张订单表t_order拆分成三张表t_order、t_user_order、t_merchant_order,t_order存储全量数据,order_id作为拆分键,t_user_order存储user_id和order_id,把user_id作为拆分键。

冗余全量表 VS 冗余关系表
  速度对比:冗余全量表速度更快,冗余关系表需要二次查询,即使有引入缓存,还是多一次网络开销;
  存储成本:冗余全量表需要几倍于冗余关系表的存储成本;
  维护代价:冗余全量表维护代价更大,涉及到数据变更时,多张表都要进行修改。

2. 多拆分键
  比如登录功能,需要使用用户名和密码登陆,这是把用户名和密码设为拆分键。

3. 拆分键+ES
  上面提到的都是条件中有拆分键的SQL执行。但是,总有一些查询条件是不包含拆分键的,同时,我们也不可能为了这些请求量并不高的查询,无限制的冗余分库分表。那么这些查询条件中没有拆分键的SQL怎么处理?以sharding-jdbc为例,有多少个分库分表,就要并发路由到多少个分库分表中执行,然后对结果进行合并。这种条件查询相对于有拆分键的条件查询性能很明显会下降很多。
  更有甚者,尤其是有些运营系统中的模糊条件查询,或者上十个条件筛选。例如淘宝我的所有订单页面,筛选条件有多个,且商品标题可以模糊匹配,这即使是单表都解决不了的问题,更不用谈分库分表了。
  拆分键+ES的模式,将分库分表所有数据全量冗余到es中,将那些复杂的查询交给es处理。

四、分库分表带来的问题

1. 事务问题
  在分库分表之后,数据存储在了不同的库上,所以本地事务失效,需要使用分布式事务解决,如果使用数据库的分布式事务支持则其效率相当低下,如果由程序控制则会存在编程上的负担并且会侵入到业务逻辑代码。
2. join问题
  数据分散在了不同库上之后,join查询变得不可用,原本一次查询就可以做的事情,最后需要多次查询才能够完成。
3. 数据库额外的负担
  在我们执行group by,order by,limit等等操作时,需要所有数据库节点同时执行并且最后还要聚合所有结果,会造成额外的负担。

五、什么时候使用分库分表

  分库分表不是最优解,反而应该是最后的解决方案。分库分表会带来相当复杂的架构以及相当大的开发、维护成本,并且如果说架构设计出现问题,其带来的问题是巨大的。只有在所有方法都不能解决性能问题时再采用分库分表,一般可以考虑的优化包括:
  设置远程数据库。如果使用的是一个整体应用程序,其中所有组件都位于同一个服务器上,那么可以通过将数据库移到它自己的机器上来提高数据库的性能。由于数据库的表保持不变,因此这不会增加分片的复杂性。
  实现缓存。如果应用程序的读取性能较低,那么缓存是一种可以优化这个问题。缓存涉及临时存储已在内存中请求的数据,以后可以快速的从缓存访问。
  读写分离。另一种有助于提高读取性能的策略,包括将数据从一个数据库服务器(主服务器)复制到一个或多个从服务器。在此之后,每次新的写操作在复制到从服务器之前都要先到主服务器,而读操作只对从服务器进行。像这样分发读写可以防止任何一台机器承担过多的负载,从而有助于防止速度下降和崩溃。请注意,创建读副本需要更多的服务器资源,因此花费更多的钱,这对一些人来说可能是一个很大的限制。
  升级到更大的服务器。在大多数情况下,将一个数据库服务器扩展到具有更多资源的计算机比分片需要更少的工作量。与读写分离一样,具有更多资源的服务器升级可能会花费更多的钱。

原文地址:https://www.cnblogs.com/ouhaitao/p/11117546.html

时间: 2024-11-06 22:31:23

分表与分库的相关文章

数据库分表和分库的原理及基于thinkPHP的实现方法

为什么要分表,分库: 当我们的数据表数据量,访问量很大,或者是使用频繁的时候,一个数据表已经不能承受如此大的数据访问和存储,所以,为了减轻数据库的负担,加快数据的存储,就需要将一张表分成多张,及将一类数据存入不同的几张表,当分表已经不能满足需求是,我们还可以分库,及用几个数据库存储. 分表会随着需求和功能的不同有不同的实现方法,下面是我做项目中的一个例子: 需求:product,product_price两张表是一对多的关系,及产品和产品每日的价格,一个产品对应几种价格,现在由于产品表数据量很大

数据库分表和分库 一点积累

数据库分库分表一般是存储了百万级乃至千万级条记录的表.这样的表过于庞大,导致数据库在查询和插入的时候耗时太长,性能低下,如果涉及联合查询的情况,性能会更加糟糕.分表和表分区的目的就是减少数据库的负担,提高数据库的效率,通常点来讲就是提高表的增删改查效率. 什么是分表? 分表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表,我们可以称为子表,每个表都对应三个文件,MYD数据文件,.MYI索引文件,.frm表结构文件.这些子表可以分布在同一块磁盘上,也可以在不同的机器上.app读写的时候

【转】mysql分库分表,数据库分库分表思路

原文:https://www.cnblogs.com/butterfly100/p/9034281.html 复制过来收藏 一. 数据切分 关系型数据库本身比较容易成为系统瓶颈,单机存储容量.连接数.处理能力都有限.当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库.优化索引,做很多操作时性能仍下降严重.此时就要考虑对其进行切分了,切分的目的就在于减少数据库的负担,缩短查询时间. 数据库分布式核心内容无非就是数据切分(Sharding),以及切分后对数据的定位.整合.数据

为什么会决定进行分库分表,分库分表过程中遇到什么难题,如何解决的?

一.为什么决定进行分库分表? 根据业务类型,和业务容量的评估,来选择和判断是否使用分库分表 当前数据库本事具有的能力,压力的评估 数据库的物理隔离,例如减少锁的争用.资源的消耗和隔离等 热点表较多,并且数据量大,可能会导致锁争抢,性能下降 数据库的高并发,数据库的读写压力过大,可能会导致数据库或系统宕机 数据库(MySQL5.7以下)连接数过高,会增加系统压力 单表数据量大,如SQL使用不当,会导致io随机读写比例高.查询慢(大表上的B+树太大,扫描太慢,甚至可能需要4层B+树) 备份和恢复时间

分表,分库算法

经典案例: 1:在memcache中分key存储.主机分布式选择主机的算法 一:利用crc32散列 <?php //范围:00-63 function crc_hash(&$keyword,$n=64) { $hash = crc32($keyword) >> 16 & 0xffff; return sprintf("%02s",$hash % $n); } ?> 二:当用户数量太多(如达到千万级别),数量量太大时,我们会根据用户名usernam

Mysql分表分库分析

对于大型的互联网应用,数据库单表的数据量可能达到千万甚至上亿级别,同时面临这高并发的压力.Master-Slave结构只能对数据库的读能力进行扩展,写操作还是集中在Master中,Master并不能无限制的挂接Slave库,如果需要对数据库的吞吐能力进行进一步的扩展,可以考虑采用分库分表的策略. 1.分表 在分表之前,首先要选中合适的分表策略(以哪个字典为分表字段,需要将数据分为多少张表),使数据能够均衡的分布在多张表中,并且不影响正常的查询.在企业级应用中,往往使用org_id(组织主键)做为

sharding-jdbc结合mybatis实现分库分表功能

最近忙于项目已经好久几天没写博客了,前2篇文章我给大家介绍了搭建基础springMvc+mybatis的maven工程,这个简单框架已经可以对付一般的小型项目.但是我们实际项目中会碰到很多复杂的场景,比如数据量很大的情况下如何保证性能.今天我就给大家介绍数据库分库分表的优化,本文介绍mybatis结合当当网的sharding-jdbc分库分表技术(原理这里不做介绍) 首先在pom文件中引入需要的依赖 <dependency> <groupId>com.dangdang</gr

分库分表

生产环境Oracle数据库大表性能出现瓶颈:该表用于事务申请.检验和销毁业务,每天千万级请求量,16个应用节点,均操作单数据库单表,当请求量短时间飙升时数据库性能出现扛不住的迹象.考虑进行分库分表优化: 1.单数据库扩展为多数据库.新增两个数据库,用来分担原来的主库压力.主库原来其他表不动,大表数据割接到分库中.在主库新增路由表,保存分库映射分表关系,通过分表定位分库,供程序识别数据源. 2.单表扩展为多表.分表均衡分布在两个新增数据库中.大表分16张表,原t_wlf分为t_wlf_0至t_wl

170123、数据库分库分表策略的具体实现方案

相关文章: 1. 使用Spring AOP实现MySQL数据库读写分离案例分析 2.MySQL5.6 数据库主从(Master/Slave)同步安装与配置详解 :http://blog.csdn.net/xlgen157387/article/details/51331244 3.MySQL主从复制的常见拓扑.原理分析以及如何提高主从复制的效率总结 :http://blog.csdn.net/xlgen157387/article/details/52451613 4.使用mysqlreplic