炸!业界难题,跨库分页的几种常见方案
为了方便举例,假设一页只有5条数据,查询第200页的SQL语句为:
步骤一:查询改写
改写为:
并投递给所有的分库,注意,这个offset的500,来自于全局offset的总偏移量1000,除以水平切分数据库个数2。 画外音:因为数据量比较大,数据随机性较强,不妨设仍然符合“数据库分库-数据均衡定理”。 如果是3个分库,则可以改写为
假设这三个分库返回的数据(time, uid)如下: 可以看到,每个分库都是返回的按照time排序的一页数据。 步骤二:找到所返回3页全部数据的最小值
故,三页数据中,time最小值来自第一个库,time_min=1487501123,这个过程只需要比较各个分库第一条数据,时间复杂度很低。 画外音:这个time_min非常重要,后文每一个步骤要都要用到time_min。 步骤三:查询二次改写 第一次改写的SQL语句是
第二次要改写成一个between语句:
第一个分库,第一次返回数据的最大值是1487501523 所以查询改写为:
第二个分库,第一次返回数据的最大值是1487501323 所以查询改写为
第三个分库,第一次返回数据的最大值是1487501553 所以查询改写为
相对第一次查询,第二次查询条件放宽了,故第二次查询会返回比第一次查询结果集更多的数据,假设这三个分库返回的数据(time, uid)如下: 可以看到:
步骤四:在每个结果集中虚拟一个time_min记录,找到time_min在全局的offset 在第一个库中,time_min在第一个库的offset是333; 在第二个库中,(1487501133, uid_aa)的offset是333(根据第一次查询条件得出的),故虚拟time_min在第二个库的offset是331; 画外音:从333往前推演。 在第三个库中,(1487501143, uid_aaa)的offset是333(根据第一次查询条件得出的),故虚拟time_min在第三个库的offset是330; 画外音:从333往前推演。 综上,time_min在全局的offset是333+331+330=994。 (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |