美文网首页
面试题-分表+分页+OrderBy如何实现

面试题-分表+分页+OrderBy如何实现

作者: 别明天就今天吧 | 来源:发表于2020-08-08 16:48 被阅读0次

    "分表后分页",在之前的文章里提过这个点,但是不够详细,最近笔者在工作也遇到了类似的问题,详细的说下这个过程如何实现。

    场景:后台系统中的一个订单分页查询功能,乍一看很简单嘛,但是这张订单表分了3张表,分表键是用户标识,比如需要查询第二页的内容并且按照升序排序,该怎么实现呢?

    分表后数据分散在各个库,会出现很多种情况:

    数据都在1表或都在2表、2表,极端情况

    数据在1,2,3表完全一致,极端情况

    数据在1,2,3表各自包含一部分,这也是最常见的情况

    【假设】一页10条数据,查询第二页的数据,未分表时的实现:

    select * from order order by create_time asc limit 10,10;

    【假设】分了3张表,分表后的实现:

     实现1:全局查询方式

    第一步:分表查询0,10+10的数据

    select * from order_1 order by create_time asc limit 0,(10+10);

        select * from order_2 order by create_time asc limit 0,(10+10);

        select * from order_3 order by create_time asc limit 0,(10+10);

    第二步:汇总结果,内存排序,获取limit 10,10

        把这个三个查询出的List<Order>,汇总到一个List,并且按照时间升序排序,取出第10条到第10+10条的数据。

    实现1的优点:满足要求,实现简单,数据完整。

    实现1的缺点:需要查询大量的数据,耗时,好网络带宽,汇总结构还需要大量数据的内存排序,耗内存,耗CPU,随着页码增加,比如查第100页,那就需要每张表limit 0,(100+10),很恐怖。

     实现2:二次查找

    第一步:limit 10,10中,拿到第一个10除以分表数3,结果取整为3;

    第二步:

    select * from order_1 order by create_time asc limit 3,10;

        select * from order_2 order by create_time asc limit 3,10;

        select * from order_3 order by create_time asc limit 3,10;

    获取到以上3个List,分别取出第一条数据的时间,按照时间比较后取到最小的一条数据,min_create_time;

    第三步:

    select * from order_1 where between min_create_time and order1_min_create_time;

        select * from order_2 where between min_create_time and order2_min_create_time; 

        select * from order_3 where between min_create_time and order3_min_create_time; 

    其中每条Sql里的orderX_min_create_time,是第二步每个List的第一条数据的时间,获取到以上sql的查询结果List<Order>.

    第四步:

            找到min_create_time在各个表的位置,也就确定了min_create_time在全局表的位置,合并集合就能找到limit 10,10的数据了.

        第二种方式,比较巧妙,在数据极端的情况下会有问题,但是正常来说不会出现这种情况的数据情况,如下图

    感谢各位老铁阅读,更多请关注公众号:别明天就今天吧

    相关文章

      网友评论

          本文标题:面试题-分表+分页+OrderBy如何实现

          本文链接:https://www.haomeiwen.com/subject/nzphdktx.html