数据库【分库分表】

发布时间 2023-10-30 17:23:02作者: 木乃伊人

一、场景

       由于用户数量越来越大会出现以下问题:

  1. 订单量剧增,单表数据量已经达到了千万的级别了,这个时候的索引查询已经很慢了,所以现在我们的类似这些大数据表的查询性能很差。
  2. 数据量持续增加,现在我们的磁盘大部分空间都被使用,导致数据库的复制备份操作很缓慢,所以,目前数据库系统已不能满足现在的数据量级。
  3. 我们整个系统的所有业务,订单,用户,优惠券、政策等等都在一个数据库系统,耦合性太高,数据不隔离。
  4. 像每天大量的用户关注、行为数据以及订单数据的写入,导致系统的写入性能持续下降。

      以上问题均是由于打冰法的写入操作导致目前的系统读写性能下降,并且系统可用性也在降低,这些就需要将这些数据进行分片,均摊我们整个数据库的压力,同时解决单机数据容量以及性能的问题。业界比较流行的方法就是分库分表方案。

二、垂直拆分

       垂直切分,就是将表按列竖着拆分。不同的数据库对应不同的业务,比如我们可以将用户相关的表放到用户数据节点里,订单相关的表放到订单数据节点,关注相关的表放到关注数据库节点。好处就是,关注数据库庞大到了几亿的量级如果影响到了数据的操作,但是并不影响用户的登录和浏览、搜索和下单操作,起到了很好的数据隔离作用。

       【例子】

        以前,我们用户表、关注表、订单表都在同一个库里面,也就是在我们的主库中,后来经过拆分后,它们分别被拆到用户库、关注库、订单库等。

              

        小结:垂直拆分这种方案,其实在我们中等规模的互联网公司里都会首先使用到,但是,随着数据的增加,这种单库里面的表还是会面临瓶颈的,如关注表数据,虽然拆到了关注库里面,但是关注表数据都已经好几亿了,仍是会影响我们这块业务的。所以说,垂直拆分只能暂缓我们的问题,但是,像那种单表数据骤增的情况还是需要采取另一种方法的,那就是我们下面要说的水平拆分。

 三、水平拆分

        水平拆分,就是按列拆分,减少单表的数量值。

        3.1、有哪些拆分规则

                1、 按照表中某一字段取哈希值进行拆分,例如我们的用户表,如果将其拆分为16个库,每个库64张表,那么,我们就将UID哈希,为什么哈希大家知道吧,前面文章分析了hashmap,应该都懂吧。然后将哈希值对16取余,得到哪一个数据库,然后对64取余就知道哪个表。这种规则比较适用于这种实体类的表。

                                 

              2、按照某一个表字段的区间做拆分,这里最常使用就是日期字段了,比如我们关注表的创建时间,比如我们要查某个月的关注数据,就可以将月份数据放进对应月份表中,这样我们就可以根据创建时间来定位到我们数据存储在哪张表里面,然后在根据我们的查询条件进行相应的查询。 

                              

        3.2、小结

                 分库分表后,虽然解决了数据库瓶颈,并发写入和读取的问题,也解决了扩展和数据隔离的问题,但是引入了分库分表,也会带来一些问题。

四、解决分库分表带来的问题

       4.1、分区键

               分区键就是我们用来进行分库分表的字段,我们每次查询的时候都必须得带上这个字段,才能找到数据所在的库和表,我们将上面用户数据按照uid进行分库分表的,那如果现在我想按照昵称来查询怎么办呢。

  1. 建议另外建立一张UID和昵称的映射表。
  2. 通过昵称查询出UID。
  3. 通过UID就可以进行定位库和表。

      4.2、多表JOIN

               我们现在的单表数据都被分到多库多表中了,然后有些程序员之前写的那些连表join 操作怎么办,跨库了,就不能使用JOIN了。所以这块我们需要将他们放到我们业务代码中进行处理了,其实代码中处理我们会更清晰一些 。 

      4.3、统计类

               和上面JOIN类似,类似统计的count()就不能使用了,然后这块我们建议是,通过另外建一张表或者放到redis缓存里面,最后再合并就行了,也很简单。        

      4.4、最后建议

               在我们的业务中不要一开始就去分库分表,在没必要的情况下不要去分库分表;如果真的要分库分表,在公司资源充足下,建议一次性分到位,会给你很爽的感觉,比如分16个库64张表,资源紧缺的话,我们就根据业务来分。