炸!业界难题,跨库分页的几种常见方案(2)
缺点显而易见:
“全局视野法”虽然性能较差,但其业务无损,数据精准,不失为一种方案,有没有性能更优的方案呢? “任何脱离业务的架构设计都是耍流氓”,技术方案需要折衷,在技术难度较大的情况下,业务需求的折衷能够极大的简化技术方案。 方案二:禁止跳页查询法 在数据量很大,翻页数很多的时候,很多产品并不提供“直接跳到指定页面”的功能,而只提供“下一页”的功能,这一个小小的业务折衷,就能极大的降低技术方案的复杂度。 如上图,不能跳页,那么第一次只能够查第一页: (1)将查询
改写成
(2)上述改写和offset 0 limit 100的效果相同,都是每个分库返回了一页数据(上图中粉色部分); (3)服务层得到2页数据,内存排序,取出前100条数据,作为最终的第一页数据,这个全局的第一页数据,一般来说每个分库都包含一部分数据(如上图粉色部分); 这个方案也需要服务器内存排序,岂不是和“全局视野法”一样么?第一页数据的拉取确实一样,但每一次“下一页”拉取的方案就不一样了。 点击“下一页”时,需要拉取第二页数据,在第一页数据的基础之上,能够找到第一页数据time的最大值: 这个上一页记录的time_max,会作为第二页数据拉取的查询条件: (1)将查询
改写成
(2)这下不是返回2页数据了(“全局视野法,会改写成offset 0 limit 200”),每个分库还是返回一页数据(如上图中粉色部分); (3)服务层得到2页数据,内存排序,取出前100条数据,作为最终的第2页数据,这个全局的第2页数据,一般来说也是每个分库都包含一部分数据(如上图粉色部分); 如此往复,查询全局视野第100页数据时,不是将查询条件改写为
而是改写为
以保证数据的传输量和排序的数据量不会随着不断翻页而导致性能下降。 方案三:允许数据精度损失法 “全局视野法”能够返回业务无损的精确数据,在查询页数较大,例如第100页时,会有性能问题,此时业务上是否能够接受,返回的100页不是精准的数据,而允许有一些数据偏差呢? 先来了解一下,数据库分库-数据均衡原理。 什么是,数据库分库-数据均衡原理? 使用patition key进行分库,在数据量较大,数据分布足够随机的情况下,各分库所有非patition key属性,在各个分库上,数据分布的统计概率情况是一致的。 例如,在uid随机的情况下,使用uid取模分两库,db0和db1:
利用这一原理,要查询全局100页数据,只要将:
改写为
即每个分库偏移一半(4950),获取半页数据(50条),得到的数据集的并集,基本能够认为,是全局数据的offset 9900 limit 100的数据,当然,这一页数据并不是精准的。 根据实际业务经验,用户都要查询第100页网页、帖子、邮件的数据了,这一页数据的精准性损失,业务上往往是可以接受的,但此时技术方案的复杂度大大降低了,既不需要返回更多的数据,也不需要进行服务内存排序了。 画外音:如果业务能够接受,这种方案的性能最好,强烈推荐。 方案四:二次查询法 有没有一种技术方案,即能够满足业务的精确需要,无需业务折衷,又高性能的方法呢?这就是接下来要介绍的终极武器,“二次查询法”。 (编辑:ASP站长网) |