水平分表后如何分页查询

580 阅读3分钟

当数据量日益增长,查询性能不断下降,我们将不得不对数据表进行拆分,当我们数据表在进行了水平拆分后,分页查询将会收到一些限制,并且针对于不同的分表策略,分页的规则也会有所不同。

背景

随着项目上线时间的不断变长,数据表的数据量不断增多,查询速度日渐变慢,客户反馈系统响应慢。当数据表达到一定量级之后,且垂直拆分无效之后,就需要对数据进行水平分表,水平分表是一个难点,我们需要考虑多方面内容,需要去衡量自己的业务增长,选对分表方式能够有效的降低数据便宜,使扩容更加平滑。当业务增长缓慢,但当系统使用久之后出现性能问题,我认为抽离历史数据也是不错的方案。

分库分表方案选型可参考之前文章收好这份武林秘籍,让你分库分表再无烦恼

当我们水平分表之后,困扰我们另一个问题就是分表查询了,下面我们就来探讨一下,数据打散在各个分表,我们该采取什么方式,高效的聚合数据,并能按照一定规则排序分页。

方案

方案一 分表键查询

分表后,使用最多的查询条件无疑是分表键,比如说我们以用户ID为分表键,当我们查询某一用户的具体信息时,就直接可以通过分表键路由到该键所在的库中查询。这样单个库就可以支持我们分页及排序。

方案二 非分表键的关键键查询

就用最经典的电商案例举例,最常用的查询无非是买家查询与卖家查询,一般这种时候会采用数据冗余的方案,基于买家和卖家分别做一套分表,当以买家为查询条件路由到买家分表,当以卖家为条件,路由到卖家分表,这种就是典型的空间换时间。

具体落地的时候可以某一方为主,负责写入,另一方只提供查询服务,通过订阅bin log自动生成。

方案三 全量冗余

除了分表键,关键键查询,其他的查询该采用什么方案,一般来说大部分公司会采用OLAP的数据库全量冗余一份数据,这种数据库特点就是不支持事务,查询速度快,支持大数据量。

方案四 全局查询再聚合

当我们在使用非分表键,且没有冗余数据的时候查询就会有多种情况出现

例如:数据都在某一张表中、数据在每个表一半、数据每一个表包含一部分

在查询的时候我们并不清楚,数据会怎么分配,就只能把每个表都满足的数据查出来,再排序,分页

将 limit x,y 改写成 limit x + y

然后在内存中排序,然后再limit y

优点: 业务无损,精准查找

缺点: 每个库表返回大量数据开销大,需要二次排序浪费算力,深度分页性能极速下降

优化方案:

  1. 禁止跳页,每次查询带着上一页条件,减少深度分页性能下降问题

  2. a. 二次查询,分表数为n,将 limit x,y 改写成 limit x / n,y

    b. 取n个表排序字段最小值 min,以及每个表排序字段最大值 max_n

    c. 排序字段 between min and max_n

    d. 然后汇总在内存中,然后再排序分页

  3. 允许精度丢失,分表数为n,将 limit x,y 改写成 limit x / n,y /n,然后聚合结果