精华内容
下载资源
问答
  • 分库分表是什么 下边以电商系统中的例子来说明,下图是电商系统卖家模块的表结构: 通过以下SQL能够获取到商品相关的店铺信息、地理区域信息: SELECT p.*,r.[地理区域名称],s.[店铺名称],s.[信誉] FROM [商品信息]...

    分库分表是什么

    下边以电商系统中的例子来说明,下图是电商系统卖家模块的表结构:
    在这里插入图片描述
    通过以下SQL能够获取到商品相关的店铺信息、地理区域信息:

    SELECT p.*,r.[地理区域名称],s.[店铺名称],s.[信誉]
    FROM [商品信息] p 
    LEFT JOIN [地理区域] r ON p.[产地] = r.[地理区域编码]
    LEFT JOIN [店铺信息] s ON s.id = p.[所属店铺]
    WHERE p.id = ?
    

    随着公司业务快速发展,数据库中的数据量猛增,访问性能也变慢了,优化迫在眉睫。分析一下问题出现在哪儿呢? 关系型数据库本身比较容易成为系统瓶颈,单机存储容量、连接数、处理能力都有限。当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库、优化索引,做很多操作时性能仍下降严重。

    方案1:

    通过提升服务器硬件能力来提高数据处理能力,比如增加存储容量 、CPU等,这种方案成本很高,并且如果瓶颈在MySQL本身那么提高硬件也是有很的。

    方案2:

    把数据分散在不同的数据库中,使得单一数据库的数据量变小来缓解单一数据库的性能问题,从而达到提升数据库性能的目的,如下图:将电商数据库拆分为若干独立的数据库,并且对于大表也拆分为若干小表,通过这种数据库拆分的方法来解决数据库的性能问题。
    在这里插入图片描述
    分库分表就是为了解决由于数据量过大而导致数据库性能降低的问题,将原来独立的数据库拆分成若干数据库组成 ,将数据大表拆分成若干数据表组成,使得单一数据库、单一数据表的数据量变小,从而达到提升数据库性能的目的。

    垂直分表

    分库分表包括分库和分表两个部分,在生产中通常包括:垂直分库、水平分库、垂直分表、水平分表四种方式。
    先说 垂直分表:
    通常在商品列表中是不显示商品详情信息的,如下图:
    在这里插入图片描述
    用户在浏览商品列表时,只有对某商品感兴趣时才会查看该商品的详细描述。因此,商品信息中商品描述字段访问频次较低,且该字段存储占用空间较大,访问单个数据IO时间较长;商品信息中商品名称、商品图片、商品价格等其他字段数据访问频次较高。

    由于这两种数据的特性不一样,因此他考虑将商品信息表拆分如下:

    将访问频次低的商品描述信息单独存放在一张表中,访问频次较高的商品基本信息单独放在一张表中。
    在这里插入图片描述
    商品列表可采用以下sql:

    SELECT p.*,r.[地理区域名称],s.[店铺名称],s.[信誉]
    FROM [商品信息] p 
    LEFT JOIN [地理区域] r ON p.[产地] = r.[地理区域编码]
    LEFT JOIN [店铺信息] s ON s.id = p.[所属店铺]
    WHERE...ORDER BY...LIMIT...
    

    需要获取商品描述时,再通过以下sql获取:

    SELECT *
    FROM [商品描述] 
    WHERE [商品ID] = ?
    

    垂直分表定义:将一个表按照字段分成多表,每个表存储其中一部分字段。
    它带来的提升是:

    1.为了避免IO争抢并减少锁表的几率,查看详情的用户与商品信息浏览互不影响

    2.充分发挥热门数据的操作效率,商品信息的操作的高效率不会被商品描述的低效率所拖累。

    为什么大字段IO效率低:第一是由于数据量本身大,需要更长的读取时间;第二是跨页,页是数据库存储单位,很多查找及定位操作都是以页为单位,单页内的数据行越多数据库整体性能越好,而大字段占用空间大,单页内存储行数少,因此IO效率较低。第三,数据库以行为单位将数据加载到内存中,这样表中字段长度较短且访问频率较高,内存能加载更多的数据,命中率更高,减少了磁盘IO,从而提升了数据库性能。

    一般来说,某业务实体中的各个数据项的访问频次是不一样的,部分数据项可能是占用存储空间比较大的BLOB或是TEXT。例如上例中的商品描述。所以,当表数据量很大时,可以将表按字段切开,将热门字段、冷门字段分开放置在不同库中,这些库可以放在不同的存储设备上,避免IO争抢。垂直切分带来的性能提升主要集中在热门数据的操作效率上,而且磁盘争用情况减少。

    通常我们按以下原则进行垂直拆分:

    1. 把不常用的字段单独放在一张表;
    2. 把text,blob等大字段拆分出来放在附表中;
    3. 经常组合查询的列放在一张表中;

    垂直分库

    通过垂直分表性能得到了一定程度的提升,但是还没有达到要求,并且磁盘空间也快不够了,因为数据还是始终限制在一台服务器,库内垂直分表只解决了单一表数据量过大的问题,但没有将表分布到不同的服务器上,因此每个表还是竞争同一个物理机的CPU、内存、网络IO、磁盘。

    经过思考,他把原有的SELLER_DB(卖家库),分为了PRODUCT_DB(商品库)和STORE_DB(店铺库),并把这两个库分散到不同服务器,如下图:
    在这里插入图片描述
    由于商品信息与商品描述业务耦合度较高,因此一起被存放在PRODUCT_DB(商品库);而店铺信息相对独立,因此单独被存放在STORE_DB(店铺库)。

    垂直分库是指按照业务将表进行分类,分布到不同的数据库上面,每个库可以放在不同的服务器上,它的核心理念是专库专用。

    它带来的提升是:

    • 解决业务层面的耦合,业务清晰

    • 能对不同业务的数据进行分级管理、维护、监控、扩展等

    • 高并发场景下,垂直分库一定程度的提升IO、数据库连接数、降低单机硬件资源的瓶颈

      垂直分库通过将表按业务分类,然后分布在不同数据库,并且可以将这些数据库部署在不同服务器上,从而达到多个服务器共同分摊压力的效果,但是依然没有解决单表数据量过大的问题。

    水平分库

    经过垂直分库后,数据库性能问题得到一定程度的解决,但是随着业务量的增长,PRODUCT_DB(商品库)单库存储数据已经超出预估。粗略估计,目前有8w店铺,每个店铺平均150个不同规格的商品,再算上增长,那商品数量得往1500w+上预估,并且PRODUCT_DB(商品库)属于访问非常频繁的资源,单台服务器已经无法支撑。此时该如何优化?

    再次分库?但是从业务角度分析,目前情况已经无法再次垂直分库。

    尝试水平分库,将店铺ID为单数的和店铺ID为双数的商品信息分别放在两个库中。

    在这里插入图片描述
    也就是说,要操作某条数据,先分析这条数据所属的店铺ID。如果店铺ID为双数,将此操作映射至RRODUCT_DB1(商品库1);如果店铺ID为单数,将操作映射至RRODUCT_DB2(商品库2)。此操作要访问数据库名称的表达式为RRODUCT_DB[店铺ID%2 + 1] 。

    水平分库是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。

    垂直分库是把不同表拆到不同数据库中,它是对数据行的拆分,不影响表结构

    它带来的提升是:

    • 解决了单库大数据,高并发的性能瓶颈。
    • 提高了系统的稳定性及可用性。

    稳定性体现在IO冲突减少,锁定减少,可用性指某个库出问题,部分可用`

    当一个应用难以再细粒度的垂直切分,或切分后数据量行数巨大,存在单库读写、存储性能瓶颈,这时候就需要进行水平分库了,经过水平切分的优化,往往能解决单库存储量及性能瓶颈。但由于同一个表被分配在不同的数据库,需要额外进行数据操作的路由工作,因此大大提升了系统复杂度。

    水平分表

    按照水平分库的思路对他把PRODUCT_DB_X(商品库)内的表也可以进行水平拆分,其目的也是为解决单表数据量大的问题,如下图:
    在这里插入图片描述
    与水平分库的思路类似,不过这次操作的目标是表,商品信息及商品描述被分成了两套表。如果商品ID为双数,将此操作映射至商品信息1表;如果商品ID为单数,将操作映射至商品信息2表。此操作要访问表名称的表达式为商品信息[商品ID%2 + 1] 。

    水平分表是在同一个数据库内,把同一个表的数据按一定规则拆到多个表中。

    它带来的提升是:

    • 优化单一表数据量过大而产生的性能问题

    • 避免IO争抢并减少锁表的几率

      库内的水平分表,解决了单一表数据量过大的问题,分出来的小表中只包含一部分数据,从而使得单个表的数据量变小,提高检索性能。

    总结

    垂直分表:可以把一个宽表的字段按访问频次、是否是大字段的原则拆分为多个表,这样既能使业务清晰,还能提升部分性能。拆分后,尽量从业务角度避免联查,否则性能方面将得不偿失。

    垂直分库:可以把多个表按业务耦合松紧归类,分别存放在不同的库,这些库可以分布在不同服务器,从而使访问压力被多服务器负载,大大提升性能,同时能提高整体架构的业务清晰度,不同的业务库可根据自身情况定制优化方案。但是它需要解决跨库带来的所有复杂问题。

    水平分库:可以把一个表的数据(按数据行)分到多个不同的库,每个库只有这个表的部分数据,这些库可以分布在不同服务器,从而使访问压力被多服务器负载,大大提升性能。它不仅需要解决跨库带来的所有复杂问题,还要解决数据路由的问题(数据路由问题后边介绍)。

    水平分表:可以把一个表的数据(按数据行)分到多个同一个数据库的多张表中,每个表只有这个表的部分数据,这样做能小幅提升性能,它仅仅作为水平分库的一个补充优化。

    一般来说,在系统设计阶段就应该根据业务耦合松紧来确定垂直分库,垂直分表方案,在数据量及访问压力不是特别大的情况,首先考虑缓存、读写分离、索引技术等方案。若数据量极大,且持续增长,再考虑水平分库水平分表方案。

    Sharding-jdbc视频分享

    分库分表生产方案Sharding-jdbc视频分享

    展开全文
  • 本文着重介绍sharding切分策略,如果你对数据库sharding缺少基本的了解,请参考我另一篇从基础理论全面介绍sharding的文章:数据库Sharding的基本思想和切分策略 第一部分:...数据库分库分表(sharding)实施策略图解

    推荐:博主历时三年倾注大量心血创作的大数据平台架构与原型实现:数据中台建设实战一书已由知名IT图书品牌电子工业出版社博文视点出版发行,真诚推荐给每一位读者!点击重磅推荐:建大数据平台太难了!给我发个工程原型吧!了解图书详情,扫码进入京东手机购书页面!

     

     

    本文原文连接: http://blog.csdn.net/bluishglc/article/details/7696085 ,转载请注明出处!本文着重介绍sharding切分策略,如果你对数据库sharding缺少基本的了解,请参考我另一篇从基础理论全面介绍sharding的文章:数据库Sharding的基本思想和切分策略

     

    第一部分:实施策略

     

     

    图1.数据库分库分表(sharding)实施策略图解(点击查看大图)


    1.准备阶段

    对数据库进行分库分表(Sharding化)前,需要开发人员充分了解系统业务逻辑和数据库schema.一个好的建议是绘制一张数据库ER图或领域模型图,以这类图为基础划分shard,直观易行,可以确保开发人员始终保持清醒思路。对于是选择数据库ER图还是领域模型图要根据项目自身情况进行选择。如果项目使用数据驱动的开发方式,团队以数据库ER图作为业务交流的基础,则自然会选择数据库ER图,如果项目使用的是领域驱动的开发方式,并通过OR-Mapping构建了一个良好的领域模型,那么领域模型图无疑是最好的选择。就我个人来说,更加倾向使用领域模型图,因为进行切分时更多的是以业务为依据进行分析判断,领域模型无疑更加清晰和直观。

    2.分析阶段

    1. 垂直切分

    垂直切分的依据原则是:将业务紧密,表间关联密切的表划分在一起,例如同一模块的表。结合已经准备好的数据库ER图或领域模型图,仿照活动图中的泳道概念,一个泳道代表一个shard,把所有表格划分到不同的泳道中。下面的分析示例会展示这种做法。当然,你也可以在打印出的ER图或模型图上直接用铅笔圈,一切取决于你自己的喜好。

    2. 水平切分
    垂直切分后,需要对shard内表格的数据量和增速进一步分析,以确定是否需要进行水平切分。

    2.1若划分到一起的表格数据增长缓慢,在产品上线后可遇见的足够长的时期内均可以由单一数据库承载,则不需要进行水平切分,所有表格驻留同一shard,所有表间关联关系会得到最大限度的保留,同时保证了书写SQL的自由度,不易受join、group by、order by等子句限制。

    2.2 若划分到一起的表格数据量巨大,增速迅猛,需要进一步进行水平分割。进一步的水平分割就这样进行:

    2.2.1.结合业务逻辑和表间关系,将当前shard划分成多个更小的shard,通常情况下,这些更小的shard每一个都只包含一个主表(将以该表ID进行散列的表)和多个与其关联或间接关联的次表。这种一个shard一张主表多张次表的状况是水平切分的必然结果。这样切分下来,shard数量就会迅速增多。如果每一个shard代表一个独立的数据库,那么管理和维护数据库将会非常麻烦,而且这些小shard往往只有两三张表,为此而建立一个新库,利用率并不高,因此,在水平切分完成后可再进行一次“反向的Merge”,即:将业务上相近,并且具有相近数据增长速率(主表数据量在同一数量级上)的两个或多个shard放到同一个数据库上,在逻辑上它们依然是独立的shard,有各自的主表,并依据各自主表的ID进行散列,不同的只是它们的散列取模(即节点数量)必需是一致的。这样,每个数据库结点上的表格数量就相对平均了。

    2.2.2. 所有表格均划分到合适的shard之后,所有跨越shard的表间关联都必须打断,在书写sql时,跨shard的join、group by、order by都将被禁止,需要在应用程序层面协调解决这些问题。

    特别想提一点:经水平切分后,shard的粒度往往要比只做垂直切割的粒度要小,原单一垂直shard会被细分为一到多个以一个主表为中心关联或间接关联多个次表的shard,此时的shard粒度与领域驱动设计中的“聚合”概念不谋而合,甚至可以说是完全一致,每个shard的主表正是一个聚合中的聚合根!

    3.实施阶段


    如果项目在开发伊始就决定进行分库分表,则严格按照分析设计方案推进即可。如果是在中期架构演进中实施,除搭建实现sharding逻辑的基础设施外(关于该话题会在下篇文章中进行阐述),还需要对原有SQL逐一过滤分析,修改那些因为sharding而受到影响的sql.

    第二部分:示例演示

    本文选择一个人尽皆知的应用:jpetstore来演示如何进行分库分表(sharding)在分析阶段的工作。由于一些个人原因,演示使用的jpetstore来自原ibatis官方的一个Demo版本,SVN地址为:http://mybatis.googlecode.com/svn/tags/java_release_2.3.4-726/jpetstore-5。关于jpetstore的业务逻辑这里不再介绍,这是一个非常简单的电商系统原型,其领域模型如下图:

     

    图2. jpetstore领域模型

     

    由于系统较简单,我们很容易从模型上看出,其主要由三个模块组成:用户,产品和订单。那么垂直切分的方案也就出来了。接下来看水平切分,如果我们从一个实际的宠物店出发考虑,可能出现数据激增的单表应该是Account和Order,因此这两张表需要进行水平切分。对于Product模块来说,如果是一个实际的系统,Product和Item的数量都不会很大,因此只做垂直切分就足够了,也就是(Product,Category,Item,Iventory,Supplier)五张表在一个数据库结点上(没有水平切分,不会存在两个以上的数据库结点)。但是作为一个演示,我们假设产品模块也有大量的数据需要我们做水平切分,那么分析来看,这个模块要拆分出两个shard:一个是(Product(主),Category),另一个是(Item(主),Iventory,Supplier),同时,我们认为:这两个shard在数据增速上应该是相近的,且在业务上也很紧密,那么我们可以把这两个shard放在同一个数据库节点上,Item和Product数据在散列时取一样的模。根据前文介绍的图纸绘制方法,我们得到下面这张sharding示意图:

     

    图3. jpetstore sharding示意图

     

    对于这张图再说明几点:


    1.使用泳道表示物理shard(一个数据库结点)

    2.若垂直切分出的shard进行了进一步的水平切分,但公用一个物理shard的话,则用虚线框住,表示其在逻辑上是一个独立的shard。

    3.深色实体表示主表

    4.X表示需要打断的表间关联

     

     

    展开全文
  • mysql 分表

    2018-11-17 10:40:25
    关于mysql的分表技术实现方法。以及分表设计, 及简单的代码实例。
  • 在谈论数据库架构和数据库优化的时候,我们经常会听到“分库分表”、“分片”、“Sharding”…这样的关键词。让人感到高兴的是,这些朋友所服务的公司业务量正在(或者即将面临)高速增长,技术方面也面临着一些挑战...

    在谈论数据库架构和数据库优化的时候,我们经常会听到“分库分表”、“分片”、“Sharding”…这样的关键词。让人感到高兴的是,这些朋友所服务的公司业务量正在(或者即将面临)高速增长,技术方面也面临着一些挑战。让人感到担忧的是,他们系统真的就需要“分库分表”了吗?“分库分表”有那么容易实践吗?为此,笔者整理了分库分表中可能遇到的一些问题,并结合以往经验介绍了对应的解决思路和建议。

    垂直分表

    垂直分表在日常开发和设计中比较常见,通俗的说法叫做“大表拆小表”,拆分是基于关系型数据库中的“列”(字段)进行的。通常情况,某个表中的字段比较多,可以新建立一张“扩展表”,将不经常使用或者长度较大的字段拆分出去放到“扩展表”中,如下图所示:

     

    小结

     

    在字段很多的情况下,拆分开确实更便于开发和维护(笔者曾见过某个遗留系统中,一个大表中包含100多列的)。某种意义上也能避免“跨页”的问题(MySQL、MSSQL底层都是通过“数据页”来存储的,“跨页”问题可能会造成额外的性能开销,这里不展开,感兴趣的朋友可以自行查阅相关资料进行研究)。

    拆分字段的操作建议在数据库设计阶段就做好。如果是在发展过程中拆分,则需要改写以前的查询语句,会额外带来一定的成本和风险,建议谨慎。

    垂直分库

    垂直分库在“微服务”盛行的今天已经非常普及了。基本的思路就是按照业务模块来划分出不同的数据库,而不是像早期一样将所有的数据表都放到同一个数据库中。如下图:


    小结

    系统层面的“服务化”拆分操作,能够解决业务系统层面的耦合和性能瓶颈,有利于系统的扩展维护。而数据库层面的拆分,道理也是相通的。与服务的“治理”和“降级”机制类似,我们也能对不同业务类型的数据进行“分级”管理、维护、监控、扩展等。

    众所周知,数据库往往最容易成为应用系统的瓶颈,而数据库本身属于“有状态”的,相对于Web和应用服务器来讲,是比较难实现“横向扩展”的。数据库的连接资源比较宝贵且单机处理能力也有限,在高并发场景下,垂直分库一定程度上能够突破IO、连接数及单机硬件资源的瓶颈,是大型分布式系统中优化数据库架构的重要手段。

    然后,很多人并没有从根本上搞清楚为什么要拆分,也没有掌握拆分的原则和技巧,只是一味的模仿大厂的做法。导致拆分后遇到很多问题(例如:跨库join,分布式事务等)。

    水平分表

    水平分表也称为横向分表,比较容易理解,就是将表中不同的数据行按照一定规律分布到不同的数据库表中(这些表保存在同一个数据库中),这样来降低单表数据量,优化查询性能。最常见的方式就是通过主键或者时间等字段进行Hash和取模后拆分。如下图所示:

     

    小结

    水平分表,能够降低单表的数据量,一定程度上可以缓解查询性能瓶颈。但本质上这些表还保存在同一个库中,所以库级别还是会有IO瓶颈。所以,一般不建议采用这种做法。

    水平分库分表

    水平分库分表与上面讲到的水平分表的思想相同,唯一不同的就是将这些拆分出来的表保存在不同的数据中。这也是很多大型互联网公司所选择的做法。如下图:

     

    某种意义上来讲,有些系统中使用的“冷热数据分离”(将一些使用较少的历史数据迁移到其他的数据库中。而在业务功能上,通常默认只提供热点数据的查询),也是类似的实践。在高并发和海量数据的场景下,分库分表能够有效缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源的瓶颈。当然,投入的硬件成本也会更高。同时,这也会带来一些复杂的技术问题和挑战(例如:跨分片的复杂查询,跨分片事务等)

    分库分表的难点

    垂直分库带来的问题和解决思路:

    跨库join的问题

    在拆分之前,系统中很多列表和详情页所需的数据是可以通过sql join来完成的。而拆分后,数据库可能是分布式在不同实例和不同的主机上,join将变得非常麻烦。而且基于架构规范,性能,安全性等方面考虑,一般是禁止跨库join的。那该怎么办呢?首先要考虑下垂直分库的设计问题,如果可以调整,那就优先调整。如果无法调整的情况,下面笔者将结合以往的实际经验,总结几种常见的解决思路,并分析其适用场景。

    跨库Join的几种解决思路

    全局表

    所谓全局表,就是有可能系统中所有模块都可能会依赖到的一些表。比较类似我们理解的“数据字典”。为了避免跨库join查询,我们可以将这类表在其他每个数据库中均保存一份。同时,这类数据通常也很少发生修改(甚至几乎不会),所以也不用太担心“一致性”问题。

    字段冗余

    这是一种典型的反范式设计,在互联网行业中比较常见,通常是为了性能来避免join查询。

    举个电商业务中很简单的场景:

    “订单表”中保存“卖家Id”的同时,将卖家的“Name”字段也冗余,这样查询订单详情的时候就不需要再去查询“卖家用户表”。

    字段冗余能带来便利,是一种“空间换时间”的体现。但其适用场景也比较有限,比较适合依赖字段较少的情况。最复杂的还是数据一致性问题,这点很难保证,可以借助数据库中的触发器或者在业务代码层面去保证。当然,也需要结合实际业务场景来看一致性的要求。就像上面例子,如果卖家修改了Name之后,是否需要在订单信息中同步更新呢?

    数据同步

    定时A库中的tab_a表和B库中tbl_b有关联,可以定时将指定的表做同步。当然,同步本来会对数据库带来一定的影响,需要性能影响和数据时效性中取得一个平衡。这样来避免复杂的跨库查询。笔者曾经在项目中是通过ETL工具来实施的。

    系统层组装

    在系统层面,通过调用不同模块的组件或者服务,获取到数据并进行字段拼装。说起来很容易,但实践起来可真没有这么简单,尤其是数据库设计上存在问题但又无法轻易调整的时候。

    具体情况通常会比较复杂。下面笔者结合以往实际经验,并通过伪代码方式来描述。

    简单的列表查询的情况

     

    伪代码很容易理解,先获取“我的提问列表”数据,然后再根据列表中的UserId去循环调用依赖的用户服务获取到用户的RealName,拼装结果并返回。

    有经验的读者一眼就能看出上诉伪代码存在效率问题。循环调用服务,可能会有循环RPC,循环查询数据库…不推荐使用。再看看改进后的:

     

    这种实现方式,看起来要优雅一点,其实就是把循环调用改成一次调用。当然,用户服务的数据库查询中很可能是In查询,效率方面比上一种方式更高。(坊间流传In查询会全表扫描,存在性能问题,传闻不可全信。其实查询优化器都是基本成本估算的,经过测试,在In语句中条件字段有索引的时候,条件较少的情况是会走索引的。这里不细展开说明,感兴趣的朋友请自行测试)。

    小结

    简单字段组装的情况下,我们只需要先获取“主表”数据,然后再根据关联关系,调用其他模块的组件或服务来获取依赖的其他字段(如例中依赖的用户信息),最后将数据进行组装。

    通常,我们都会通过缓存来避免频繁RPC通信和数据库查询的开销。

    列表查询带条件过滤的情况

    在上述例子中,都是简单的字段组装,而不存在条件过滤。看拆分前的SQL:

     

    这种连接查询并且还带条件过滤的情况,想在代码层面组装数据其实是非常复杂的(尤其是左表和右表都带条件过滤的情况会更复杂),不能像之前例子中那样简单的进行组装了。试想一下,如果像上面那样简单的进行组装,造成的结果就是返回的数据不完整,不准确。 

    有如下几种解决思路:

    1. 查出所有的问答数据,然后调用用户服务进行拼装数据,再根据过滤字段state字段进行过滤,最后进行排序和分页并返回。

      这种方式能够保证数据的准确性和完整性,但是性能影响非常大,不建议使用。

    2. 查询出state字段符合/不符合的UserId,在查询问答数据的时候使用in/not in进行过滤,排序,分页等。过滤出有效的问答数据后,再调用用户服务获取数据进行组装。

      这种方式明显更优雅点。笔者之前在某个项目的特殊场景中就是采用过这种方式实现。

    跨库事务(分布式事务)的问题

    按业务拆分数据库之后,不可避免的就是“分布式事务”的问题。以往在代码中通过spring注解简单配置就能实现事务的,现在则需要花很大的成本去保证一致性。这里不展开介绍, 
    感兴趣的读者可以自行参考《分布式事务一致性解决方案》,链接地址: 
    http://www.infoq.com/cn/articles/solution-of-distributed-system-transaction-consistency

    垂直分库总结和实践建议

    本篇中主要描述了几种常见的拆分方式,并着重介绍了垂直分库带来的一些问题和解决思路。读者朋友可能还有些问题和疑惑。

    1. 我们目前的数据库是否需要进行垂直分库?

    根据系统架构和公司实际情况来,如果你们的系统还是个简单的单体应用,并且没有什么访问量和数据量,那就别着急折腾“垂直分库”了,否则没有任何收益,也很难有好结果。

    切记,“过度设计”和“过早优化”是很多架构师和技术人员常犯的毛病。

    2. 垂直拆分有没有原则或者技巧?

    没有什么黄金法则和标准答案。一般是参考系统的业务模块拆分来进行数据库的拆分。比如“用户服务”,对应的可能就是“用户数据库”。但是也不一定严格一一对应。有些情况下,数据库拆分的粒度可能会比系统拆分的粒度更粗。笔者也确实见过有些系统中的某些表原本应该放A库中的,却放在了B库中。有些库和表原本是可以合并的,却单独保存着。还有些表,看起来放在A库中也OK,放在B库中也合理。

    如何设计和权衡,这个就看实际情况和架构师/开发人员的水平了。

    3. 上面举例的都太简单了,我们的后台报表系统中join的表都有n个了, 
    分库后该怎么查?

    有很多朋友跟我提过类似的问题。其实互联网的业务系统中,本来就应该尽量避免join的,如果有多个join的,要么是设计不合理,要么是技术选型有误。请自行科普下OLAP和OLTP,报表类的系统在传统BI时代都是通过OLAP数据仓库去实现的(现在则更多是借助离线分析、流式计算等手段实现),而不该向上面描述的那样直接在业务库中执行大量join和统计。

    由于篇幅关系,下篇中我们再继续细聊“水平分库分表”相关的话题。

    作者介绍

    丁浪,技术架构师。关注高并发、高可用的架构设计,对系统服务化、分库分表、性能调优等方面有深入研究和丰富实践经验。热衷于技术研究和分享。

    展开全文
  • MySQL分表分表后插入sql语句,表为订单表,可以参考一下
  • 分表 JAVA 分表例子,带SQL文件 很简单的例子,就可以明白怎么分表
  • MySQL分表

    2020-04-01 11:13:06
    数据库分表常见的拆分方式有两种,分别是垂直分表和水平分表。 垂直分表带来的问题主要体现在表操作的数量要增加,原来只要一次查询就可以获取的信息,现在需要进行多次查询。 接下来讲一讲水平分表。水平分表适合...

    数据库分表常见的拆分方式有两种,分别是垂直分表和水平分表。

    垂直分表带来的问题主要体现在表操作的数量要增加,原来只要一次查询就可以获取的信息,现在需要进行多次查询。

    接下来讲一讲水平分表。水平分表适合表行数特别大的表,如果单表行数超过5000万行就必须进行分表。那是5000万不是绝对标准,当看到表的数据量达到千万级别时,作为架构师就要警觉起来。

    水平分表之后带来的第一个问题是路由。水平分表之后,某条数据具体属于哪个切分后的子表,需要增加路由算法来进行计算。这个算法会引入一定的复杂性。常见的路由算法有范围路由,哈希路由,配置路由三种。

     范围路由指的是选取有序的数据列,作为路由的条件不同,分段分散到不同的数据库表中。范围路由的优点是随着数据的增加,只需要平滑的扩充新表就可以,原有的数据不用动。缺点是不同表之前的数据分布不均匀。例如每个表存放500万条数据,如果总共有510万条数据,那么第二个表只会有10万条数据。

    Hash路由一般选用某列的哈希值进行计算,常见的Hash算法是取余。Hash路由的优点是不同表之间数据量分布均匀,缺点是扩充表时,原有数据需要重新分布。

    配置路由是采用一张新表保存数据id和数据表的映射关系。优点是配置灵活,使用简单。缺点是需要进行两次查询,此外,数据量很大时,配置表也会成为性能的瓶颈。

    数据库分表之后还带来了其他问题,比如join操作,count操作以及order by操作。数据库部分表的情况下,这些操作可以在数据库层面完成,但是数据库分表之后这些操作只能在业务逻辑层进行了。对于count操作的解决方法一般有两种,第一个是各个分表分别进行count然后将结果相加。第二种方法是新增加1个记录数表,记录数表的问题在于每次写入和删除数据时都需要操作记录数表,增加了业务逻辑的复杂性。

    展开全文
  • 1. 垂直分表 1、 原表字段有 C1, C2, C3, C4, C5, C6, C7 2、 分表后表1字段:C1, C2, C3, C4 3、 分表后表2字段:C1, C5, C6, C7 在执行查询的时候根据C1主键查询 2. 水平分表 原表字段有 C1, C2, C3, C4, C5, C6,...
  • SQL,大数据分表,SQL千万级分表,删除百万数据
  • 在我上一篇文章中说过,mysql语句的优化有局限性,mysql语句的优化都是围绕着索引去优化的,那么如果mysql中的索引也解决不了海量数据查询慢的状况,那么有了水平分表与垂直分表的出现(我就是记录一下自己的理解) ...
  • 分库分表

    2021-01-20 12:26:02
    这篇文章主要介绍分库分表,以及分库分表带来的问题、 # # 分库分表的几种形式  水平分库,本质是把相同的表放在不同的机器上。  垂直分库:本质是将多个表拆分到不同的机器上。  水平分表,本质是分表数据。  ...
  • 因此,日志分表不需要通过userId或其它字段进行取模分表。 那日志怎么分表呢?这里一共提供两个分表方法。一个是根据时间分表;一个是根据表数据总量分表。 一、根据时间分表 某个表插入时间只能在某个时间范围...
  • 垂直分表水平分表

    2017-11-14 09:58:00
    1 2 3 4 5 6 7 8 9 10 ...分表技术(表的结构不能变) 分表技术有(水平分割和垂直分割) ...当一张越来越大时候,即使添加索引还慢的话,我们可以使用分表 以qq用户表来具体的说明一下分表的操作. 思路如图 : ...
  • 在我上一篇文章中说过,mysql语句的优化有局限性,mysql语句的优化都是围绕着索引去优化的,那么如果mysql中的索引也解决不了海量数据查询慢的状况,那么有了水平分表与垂直分表的出现(我就是记录一下自己的理解)...
  • 分表策略

    2021-03-01 11:07:00
    取模分表 例如:对券信息表进行取模分表,分为0~99张表 public static Integer getShrading(String modKey,int shardKey){ return modKey.hashCode() & (shardKey - 1); } 日期分表 例如:交易订单表按月...
  • 这篇博客通过ShardingSphere实现分表不分库 一、项目概述 1、技术架构 项目总体技术选型 SpringBoot2.0.6 + shardingsphere4.0.0-RC1 + Maven3.5.4 + MySQL + lombok(插件) 2、项目说明 场景:在实际开发中,如果表...
  • 主要为大家详细介绍了MySql数据库分区和分表方法,告诉大家什么是分表和分区,mysql分表和分区有什么联系,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 这篇博客通过ShardingSphere实现分库分表 一、项目概述 1、技术架构 项目总体技术选型 SpringBoot2.0.6 + shardingsphere4.0.0-RC1 + Maven3.5.4 + MySQL + lombok(插件) 2、项目说明 场景:在实际开发中,如果表的...
  • mysql分库分表(二)

    万次阅读 2019-10-08 11:47:53
    一种可以避免数据迁移的分库分表scale-out扩容模式 一种可以避免数据迁移的分库分表scale-out扩容方式 目前绝大多数应用采取的两种分库分表规则 mod方式 dayofweek系列日期方式(所有星期1的数据在一个库/表,或...
  • 经常听到有人说“数据表太大了,需要分表”,“xxxx了,要分表”的言论,那么,到底为什么要分表?难道数据量大就要分表?mysql数据量对索引的影响本人mysql版本为5.7新增数据测试为了测试mysql索引查询是否和数据量...
  • 分表方式

    2020-01-27 19:41:18
    水平分表 针对数据量太大 1、%取模就是取余(分表永远在20以内) 做法:设置求模数,分表key %求模数 =分表的key 好处:永远不会超过指定的表数量 2、/取余就是得出结果(分表的数量无限多) 做法:设置一个表...
  • 记得,如果有人问你做数据库优化最有效的方式是什么?`SQL优化、分布式集群、分库分表!`干就完了~ 但你对分库分表理解多少呢?什么时候该分表?有几种分法儿?别想了,快上车,5分钟学会!
  • 本文讨论的数据库分表是不改变数据库表结构的水平拆分,不讨论业务的按照纵向拆分。水平拆分数据分库和分表的核心问题是表的ID唯一,然后根据唯一的ID映射到一个物理存储位置,这个映射方案要考虑到满足数据量暴增...
  • 1.分表原因1.数据过多,访问缓慢2.创建索引时重新排序,创建缓慢,并且占用大量的磁盘空间2.分表方式1.根据数据范围分表2.根据取模的方式(取余数)3.Atlas分表1.分表思路1.确定分表的库,表,字段2.确定分表的数量3....
  • 精品专栏死磕 Java 并发死磕 Sharding-jdbc死磕 Spring 之 IOC再次抛出笔者的观点,在能满足业务场景的情况下,单表>分区>单库分表...
  • Mysql中分区和分表有什么区别,各自的优缺点是什么当数据库表中数据量能够被预测到将会非常大,或者已经拥有庞大的数据时,我们应该选择分表或者分区(即使用多个数据库)来解决数据访问时的性能问题。如果单机的cpu...
  • 一、数据库瓶颈不管是IO瓶颈,还是CPU瓶颈,最终都会导致数据库的活跃连接数增加,进而逼近甚至达到数据库可承载活跃连接数的阈值。在业务Service来看就是,可用数据库... 分库和垂直分表。第二种:网络IO瓶颈,请求...
  • 1,水平分表: 例:QQ的登录表。假设QQ的用户有100亿,如果只有一张表,每个用户登录的时候数据库都要从这100亿中查找,会很慢很慢。如果将这一张表分成100份,每张表有1亿条,就小了很多,比如qq0,qq1,qq1...qq99...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 29,047
精华内容 11,618
关键字:

分表