分库-翻页 二次查询法 二次查询法 有没有一种技术方案,即能够满足业务的精确需要,无需业务折衷,又高性能的方法呢?这就是接下来要介绍的终极武器,“二次查询法”。 为了方便举例,假设一页只有 5 条数据,查询第 200 页的 SQL 语句为: select * from T order by time offset 1000 limit 5; 步骤一:查询改写 select * from T order by time offset 1000 limit 5; 改写为 select * from T order by time offset 500 limit 5; 并投递给所有的分库,注意,这个 offset 的 500,来自于全局 offset 的总偏移量 1000,除以水平切分数据库个数 2。 画外音:因为数据量比较大,数据随机性较强,不妨设仍然符合 “数据库分库 - 数据均衡定理”。 如果是 3 个分库,则可以改写为 select * from T order by time offset 333 limit 5; 假设这三个分库返回的数据 (time, uid) 如下: 可以看到,每个分库都是返回的按照 time 排序的一页数据。 步骤二:找到所返回 3 页全部数据的最小值 第一个库,5 条数据的 time 最小值是 1487501123; 第二个库,5 条数据的 time 最小值是 1487501133; 第三个库,5 条数据的 time 最小值是 1487501143; 故,三页数据中,time 最小值来自第一个库,time_min=1487501123,这个过程只需要比较各个分库第一条数据,时间复杂度很低。 画外音:这个 time_min 非常重要,后文每一个步骤要都要用到 time_min。 步骤三:查询二次改写 第一次改写的 SQL 语句是 select * from T order by time offset 333 limit 5; 第二次要改写成一个 between 语句: between 的起点是 time_min between 的终点是原来每个分库各自返回数据的最大值 第一个分库,第一次返回数据的最大值是 1487501523 所以查询改写为: select * from T order by time where time between time_min and 1487501523; 第二个分库,第一次返回数据的最大值是 1487501323 所以查询改写为 select * from T order by time where time between time_min and 1487501323; 第三个分库,第一次返回数据的最大值是 1487501553 所以查询改写为 select * from T order by time where time between time_min and 1487501553; 相对第一次查询,第二次查询条件放宽了,故第二次查询会返回比第一次查询结果集更多的数据,假设这三个分库返回的数据 (time, uid) 如下: 可以看到: 分库一的结果集,由于 time_min 来自原来的分库一,所以分库一的返回结果集和第一次查询相同(所以其实这次访问是可以省略的); 分库二的结果集,比第一次多返回了 1 条数据,头部的 1 条记录(time 最小的记录)是新的(上图中粉色记录); 分库三的结果集,比第一次多返回了 2 条数据,头部的 2 条记录(time 最小的 2 条记录)是新的(上图中粉色记录); 步骤四:在每个结果集中虚拟一个 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。 步骤五:既然得到了 time_min 在全局的 offset,就相当于有了全局视野,根据第二次的结果集,就能够得到全局 offset 1000 limit 5 的记录 第二次查询在各个分库返回的结果集是有序的,又知道了 time_min 在全局的 offset 是 994,一路排下来,容易知道全局 offset 1000 limit 5 的一页记录(上图中黄色记录)。 这种方法的优点是:可以精确的返回业务所需数据,每次返回的数据量都非常小,不会随着翻页增加数据的返回量。 转载链接:https://juejin.cn/post/6908220694929080333
《分库-翻页 二次查询法》上暂无评论!