千万级数据分页实现

海量数据分页,已经无法使用数据库自带的分页机制,比如MySQL Limit ,这会导致严重的性能问题


1.问题的提出 
在软件开发中,大数据量的查询是一个常见的问题,经常会遇到对大量数据进行查询的场景。

常见的对大数据量查询的解决方案有以下两种:

(1)、将全部数据先查询到内存中,然后在内存中进行分页,这种方式对内存占用较大,必须限制一次查询的数据量。

(2)、采用存储过程在数据库中进行分页,这种方式对数据库的依赖较大,不同的数据库实现机制不通,并且查询效率不够理想。以上两种方式对用户来说都不够友好。


2.解决思路 
通过在待查询的数据库表上增加一个用于查询的自增长字段,然后采用该字段进行分页查询,可以很好地解决这个问题。下面举例说明这种分页查询方案。

(1)、在待查询的表格上增加一个long型的自增长列,取名为“queryId” 主键增长


先按照大小顺序的倒序查出所有的queryId,

语句如下:select queryId from test_table where order by queryId desc

因为只是查询queryId字段,即使表格中的数据量很大,该查询也会很快得到结果。然后将得到的queryId保存在应用服务器的一个数组中。

用户在客户端进行翻页操作时,客户端将待查询的页号作为参数传递给应用服务器,服务器通过页号和queyId数组算出待查询的queyId最大和最小值,然后进行查询。

 算出queyId最大和最小值的算法如下,其中page为待查询的页号,pageSize为每页的大小,queryIds为第二步生成的queryId数组: 
         int startRow = (page - 1) * pageSize
        int endRow = page * pageSize - 1; 
              if (endRow >=queryIds.length) 
                { 
                    endRow = this.queryIds.length - 1; 
                } 
         long startId =queryIds[startRow]; 
         long endId =queryIds[endRow];


查询语句如下: 
String sql = "select * from test_table" + 查询条件 + "(queryId <= " + startId + " and queryId >= " + endId + ")"; 


3.效果评价 
该分页查询方法对所有数据库都适用,对应用服务器、数据库服务器、查询客户端的cpu和内存占用都较低,查询速度较快,是一个较为理想的分页查询实现方案。经过测试,查询4百万条数据,可以在3分钟内显示出首页数据,以后每一次翻页操作基本在2秒以内。内存和cpu占用无明显增长。


4. 对于大数据,我认为数据分区、分成多个表、增加内存、换更好的机器都是物理上的,当然她带来的速度的改善是有的。

     在软的方面,最有效和可行的办法是优化数据库结构和索引,对于优化数据库有根据事务型和数据仓库型分为两个方面

  偏重事务需要插入、更新速度快,所以一般这样的表索引比较少,字段数目也少

 数据仓库需要查询速度快,他一般会根据查询可能出现的条件建立所有的索引

  在大数据量的数据库中,一旦某个查询不能完全利用索引,就会形成表扫描。这是最坏的情况


    我一般是分成两个库,一个处理事务,一个处理查询,

  总的来说,只有才所有软的手段不能解决问题的情况下才采用物理的方法。





发布了186 篇原创文章 · 获赞 24 · 访问量 31万+

猜你喜欢

转载自blog.csdn.net/echocdzh/article/details/50476543
今日推荐