前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

1、简单思想

分库后,有些分页查询需要遍历所有库。 举个分页的例子,比如要求按时间顺序展示某个商家的订单,每页100条记录,假设库数量是8,我们来看下分页处理逻辑:

1.1、全局视野法:

如果取第1页数据,则需要从每个库里按时间顺序取前100条记录,8个库汇总后有800条,然后对这800条记录在应用里进行二次排序,最后取前100条。

如果取第10页数据,则需要从每个库里取前1000(100*10)条记录,汇总后有8000条记录,然后对这8000条记录二次排序后取(900,1000)条记录。

分库情况下,对于第k页记录,每个库要多取100*(k-1)条记录,所有库加起来,多取的记录更多,所以越是靠后的分页,系统要耗费更多内存和执行时间。

优点:对比没分库的情况,无论取那一页,都只要从单个DB里取100条记录,而且无需在应用内部做二次排序,非常简单。

缺点每个分库都需要返回更多的数据,增大网络传输量除了数据库要按照time排序,服务层也需要二次排序,损耗性能;随着页码的增大,性能极具下降,数据量和排序量都将大增

1.2、业务折中

禁止跳页查询不提供“直接跳到指定页面”的功能,只提供下一页的功能正常来讲,不管哪一个分库的第3页都不一定有全局第3页的所有数据,例如一下三种情况:

1、先找到上一页的time的最大值(可从前台传入),作为第二页数据拉去的查询条件,只取每页的记录数

2、这样服务层还是获得两页数据,再做一次排序,获取一页数据。

3、改进了不会因为页码增大而导致数据的传输量和排序量增大

1.3、允许数据精度丢失:

需要考虑业务员上是否接受在页码较大是返回的数据不是精准的数据。

在数据量较大,且ID映射分布足够随机的话,应该是满足等概率分布的情况的,所以取一页的数据,我们在每个数据库中取(每页数据/数据库数量)个数据。 当然这样的到的结果并不是精准的,但是当实际业务可以接受的话, 此时的技术方案的复杂度变大大降低。也不需要服务层内存排序了。

1.4、二次查询法

2 个数据库,假设一页只有5条数据,查询第200页的SQL语句为

select * from T order by time  limit 1000  5;
  1. 讲sql改写为
select * from T order by time limit  500 5;  

注意这里的500=1000/分表数量,并将这个sql下发至每个分库分表中执行,每个分库返回这个sql执行的结果。
  1. 找到所有分库返回结果的time的最小值

1568872807187

第一个库,5条数据的time最小值是1487501123
第二个库,5条数据的time最小值是1487501223

故,三页数据中,time最小值来自第一个库,time_min=1487501123,这个过程只需要比较各个分库第一条数据,时间复杂度很低
  1. 查询二次改写,第二次要改写成一个between语句,between的起点是time_min,between的终点是原来每个分库各自返回数据的最大值:
第一个分库,第一次返回数据的最大值是1487501523
所以查询改写为select * from T order by time where time between time_min and 1487501523


第二个分库,第一次返回数据的最大值是1487501699
所以查询改写为select * from T order by time where time between time_min and 1487501699

1568872940023

从上面图片可以看出,DB1比第一次查出来的数据多了两行,应为查询的范围扩大了
  1. 计算time_min这条记录在全局的偏移量

1568873945123

从而我们得知time_min这条记录在全局的偏移量值=500+497=997,其实也就是说,我们的第1000条记录的终点是time=1487501128
  1. 获取最终结果,讲第二次查询出的进行排序,最终获得结果

1568874155994

优点:可以精确的返回业务所需数据,每次返回的数据量都非常小,不会随着翻页增加数据的返回量。 

缺点:需要进行两次数据库查询

2、大宽表

如果仅仅是一些不重要的流水可以使用一张表进行记录,然后只保留一个月内的数据

3、数仓/ES

订单数据落库之后,不管你通过binlog还是MQ消息的都形式,把数据同步到数仓或者ES,他们支持的数量级对于这种查询条件来说就很简单了。同样这种方式肯定是稍微有延迟的,但是这种可控范围的延迟是可以接受的。

ContactAuthor