MySql多表分页


转自:https://www.2cto.com/database/201703/613088.html

MySql的多表分页一直是一个比较困难的问题。常见的多表分页场景主要出现在统计页面中,比如统计多维度的数据,或者按照固定顺序取多个数据表数据。

方案一:创建临时表。

创建临时表是一个最简单快捷的方案。在对数据实时性要求不高的情况下,可以创建一个临时表,使用程序整理要查询的数据,并定时把整理好的数据insert到临时表中,展示时直接从临时表中读取数据。这样做的优势是简单快速,可以把很复杂的问题简单化,并且在数据量不大的情况下有很好的表现。缺陷也很明显:实时性不高,数据量大的情况下临时表会占用大量的资源。因此个人觉得创建历史表这个方案,在项目创建初期或者快速完成内部统计功能的时候是一个很好地选择。

这个方案用于商业化的项目中一定要谨慎,因为项目上线以后,由于数据量越来越大,临时表很有可能突破预计的大小。

方案二:内存排序

内存排序的核心思想就是先把一部分要分页数据load到内存中,然后在内存中对读出的数据进行排序,然后对排序后的数据进行分页。

具体的多表分页方式可以参考文章:
业界难题-“跨库分页”的四种方案
文章中介绍了四种内存排序的方案,前三种理解起来很简单,这里着重对文章中的第四种方案“二次查询法”进行一个简单的分析,并且用java做出了实现。

首先简单介绍一下二次查询法的基本思想。
假设我们的数据库中有200条数据,分别存储在A表(order_table_accept)和B表(order_table_return)中,分页的步长是10,根据时间排序,我们要取的是第8页的数据。

假设存储时单表,那么sql非常简单

?
1
SELECT * FROM table ORDER BY create_time limit 8*10,10;

那么当我们分表查询时,首先就要把sql改写成查询两张表,如下:

?
1
2
select * from table_A order by create_time limit 8*10/2,10
select * from table_B order by create_time limit 8*10/2,10

那么这样现在我们就有了20条数据,是从A表,和B表的第40条位置开始处理的。

接下来比较这20条数据中最小的一个时间,假设是A表中查出的第一条数据:2017-03-01 17:00:00,然后查询B表结果中的最大数据,假设是 2017-03-01 17:00:10。然后改写sql进行二次查询。

?
1
select * from B where create_time  between '2017-03-01 17:00:00' and '2017-03-01 17:00:10' order by create_time

假设这次查出了12条数据,那么现在对于2017-03-01 17:00:00这个时间点,在A表中有40条数据小于该时间点。B表中有40-(12-10)条数据小于该时间点,那么可以得到,2017-03-01 17:00:00这个时间在整个数据库中的位置是40+38=78条数据,那么根据第二次查询结果,在22条数据中根据时间2017-03-01 17:00:00之后的12条数据,即可得到所需的。

猜你喜欢

转载自blog.csdn.net/qq_39081511/article/details/80513561