水平分库分表后的分页查询解决方案

例如按id取模进行水平分表分n张表,分页查询第page页的rows条数据,当前页最后一条记录是索引:currIndex = (page-1)*rows;以下为按id进行排序分页进行示例说明

主流的有4种解决方案(未经验证,仅作个人笔记):

额外保存一张表,存储所有库所有表的全部id属性;

分页查询时直接从该表查出主键,然后再根据主键去各个库、表中查询具体信息

分别查询出各个表中的前(page-1)* rows条数据

即:limit 0, (page-1)*rows:该方案在前几页查询还行,当查询页数靠后数据量很大时基本是需要取出所有分表中的所有数据,然后利用程序进行分页,这时因数据量过大而无法处理,只能限制查询的页数

限制用户只能通过上一页、下一页进行查询,不能跳页

该方案是从第一页开始查询:从各个表中取得前rows条数据,然后进行翻页到下一页时将本页的最后一条id作为参数,查询id>上一页最大值然后再取rows条数据然后从n*rows条数据中进行筛选

两轮SQL查询+内存排序
  1. 首先将需要查询的总记录的索引按表均分:start = currIndex/n;然后从各个表中查询从start开始的rows条数据:limit start, rows,一共查询出n*rows条数据;
  2. 找出第一步查询出的数据的最小值:min;然后用min对其他库、表进行二次查询补足第一次查询的数据遗漏:between min and dbMin;(dbMin为第一次查询各个库的最小值);
  3. 此时还要查询最小值所在库从它到其他库的最小值(选用其他库最小值中最大的那个)的数据;(该操作是防止最小值所在库第一次查询的10条数据到其他库第二次查询的数据(当前库中大于min的部分)之间存在断层,数据不连续)
  4. 由以上查询可以确定最小值min在全局中的位置,从而可以定位需要查询的数据的位置

在复杂查询条件下针对第四种方案的疑问

  1. 按已知查询方案可以确定查询结果在第二次返回数据中,关键问题是如何定位出真正所需要的那rows条数据?

可以在内存中通过各个库中第一次查询的数据的位置确定min在全局中的偏移量offset,由偏移量重新定位真正要查询的数据

  1. 数据在极端的分布(例如某个库从min值到第一次查询的值直接有大量数据,当然这个数据量不会超过第一次查询跳过的数量)情况下,查询会不会有问题?

有待进一步验证

  1. 存在查询条件时,是否仍然可用?

每次查询数据库携带查询条件进行查询而已,方案仍可用

每种解决方案适用于不同的分表策略,具体使用方案应结合分表策略处理

posted @ 2021-05-09 16:16  Abserver  阅读(5703)  评论(0编辑  收藏  举报