概述随着数据库中数据量日益增多,不得进行分库分表,在分库后将数据分布到不同的数据库实例(甚至物理机器)上 , 以达到降低数据量,提供系统的处理能力,但是这种架构也带来其他问题,比如本文要讲解的跨库分页查询 。
全局查询法
文章插图
test表有数据[1,2,3,4,5,6,7,8],在单库的时候,查询第2页数据并且显示2条,语句是这样的:
select * from testorder by id limit 2 offset 2
数据返回[3,4],但是数据切分以后,如果要查询,这样语句就可能就会有问题,例如:在节点1执行此语句 , 返回【6,8】, 节点2返回【5,7】,然后进行排序取前二条返回了【5,6】,可以看到此结果与实际结果不一致,所以应该对sql语句改写为:select * from testorder by id limit 0 offset 4;
然后在根据各节点返回的数据,在进行排序,筛选出第2页的2条 。缺点:
- 每个节点返回更多的数据 , 增大了网络传输量
- 服务层还需要进行二次排序,增大了服务层的计算量
- 随着页码的增大,性能会急剧下降
- 查询简单,数据准确 , 不用做业务兼容 , 数据库中间件都支持
假设db1中值为【2、4、6、8】,db2中值为【1、3、5、7】 , 根据id进行排序,返回对应的条数,在内存中对各个节点返回的数据进行排序,得到需要的数据 , 执行以下语句 , 查询第一页数据,返回结果集为【1,2】:
select * from test where id>0 order by idlimit 2;
相比以前的方案,貌似跟以前处理流程一样,但是在查询第二页时,要根据上一页的id的最大值id_max(第一页的最大id_max为2),作为第二页的最小值,那么会将如下语句:select * from testorder by id limit 2,2;
改写成:select * from test order by id> 2 limit 2
这样每个节点不用返回4页数据了,只需要返回跟第一页一样页数的数据,可以看到通过对业务的折中,性能得到大大的提升 。- 缺点:此种方案需要业务层进行处理 , 而且不能跳页查询,比如当前页是第一页,直接调到第五页,因无法获取到第四页的最大ID,所以无法查询第五页的数据
- 优点:不会随着页数的增大而影响查询性能
例如,在uid随机的情况下,使用uid取模分两库,db0和db1:
- 性别属性,如果db0库上的男性用户占比70%,则db1上男性用户占比也应为70%
- 年龄属性,如果db0库上18-28岁少女用户比例占比15%,则db1上少女用户比例也应为15%
- 时间属性,如果db0库上每天10:00之前登录的用户占比为20%,则db1上应该是相同的统计规律
文章插图
精度损失查询法示意图
利用这一原理,如上图要查询全局第二页数据 , limit 2 offset 2 改写为 limit 1 offset 1,每个分库偏移 1(一半),获取1条数据(半页),得到的数据集的并集,那么结果为【3,4】基本能够认为 , 是全局数据的limit 2 offset 2的数据,当然这里只是为了所以返回的准确数据 , 但是实际并不是精准的 。
【分库分表必会:跨库分页查询看此一篇就够了】根据实际业务经验,用户都要查询第100页网页、帖子、邮件的数据了,这一页数据的精准性损失,业务上往往是可以接受的,但此时技术方案的复杂度便大大降低了,既不需要返回更多的数据,也不需要进行服务内存排序了 。
终极大招-二次查询法以上介绍的方案或多或少都有一定缺点,那么有没有一种方式能够满足业务需要,也能满足性能要求的方法呢,有,那就是二次查询法 。
推荐阅读
- 驼奶的功效与作用,骆驼奶的成分表?
- 六个开发者必知必会的Git命令
- 大学生体测标准评分表1000米 大学生体测标准评分表
- 护发精油哪些好?警惕!美发专家告诉你护发精油哪些成分表不能用
- 5月20日13点14分怎么表白 2021年5月20日13点14分表白
- 高圆圆独自带女儿逛超市,跪地上看成分表,身边无保姆保镖超低调
- 程序员必会之最详细的ThreadPoolExecutor 线程池七大参数含义
- 火龙果的营养 火龙果的营养成分表100g
- 千分表的使用方法及读数步骤视频 千分表的使用方法
- 欧莱雅复颜精华露成分表 欧莱雅复颜精华露使用方法