日期:2014-05-18  浏览次数:20498 次

千万行数据分页方法及效率讨论
--以下是建表bigt和插入数据
CREATE   TABLE   [bigt]   (
[item]   [varchar]   (20)   COLLATE   Chinese_PRC_CI_AS   NULL   ,
[id]   [int]   IDENTITY   (1,   1)   NOT   NULL  
)   ON   [PRIMARY]
GO


declare   @i   int
select   @i=0
set   nocount   on
while     @i <20000000
begin
insert   bigt   (item)   values(null)
select   @i=@i+1
end
set   nocount   off

------解决方案--------------------
如果有模糊查询呢?
------解决方案--------------------
这个不错,顶起来。

------解决方案--------------------
其实这个问题归根结底是这样的:不应该把千万笔的数据拿出来分页。

首先:需要分页的数据是给人看才需要分页,让人在千万笔数据里筛选是不合理的。
其次:不管用什么方法,数据有千万笔都是不可否认的,一笔数据10字节的话也有 1亿字节(100M)的数据需要处理,大部分时间都用来读数据和分配内存,所以关键的问题就变成了控制io,结果集和排序方式如果是需要计算的,那计算出结果集和排序的io和开销时间无论如何省不了(如果结果集会被多次使用也许你应该考虑为结果集临时建立该有的物理表和聚集索引)。

在kw级的数据上,需要分页取出数据的话,如果能根据聚集索引按区间取出来需要数据再进行操作,通过聚集索引把规模缩到万记录以下的级别,也够人看了,性能上也就可以接受了。

不带索引预先过滤处理kw级数据除了在做数据分析的时候我认为应该在应用里坚决地制止掉,而且让人在kw数据里滚来滚去,一定要么是用户的脑袋短路,要么是程序员偷懒。


------解决方案--------------------
这个我同意。

我的意思无非就是说,不能让它出现kw笔数据一起处理的情况,无论如何要用很小的代价进行第一次的过滤。

我有也经常喜欢用可能不实用但是比较特别的方法去尝试,比如用sql语句操作com对象连自己,不过这种东西仅限于探讨,因为数据库不是设计来做这个的,所以做这种工作它一般来说不仅慢而且麻烦,我们可以选择更好的工具和方式完成它。

像分页,其实就不是sql语句应该做的事情,即使勉强做到了,也都很不自然而且低效,其实你的第一种方法如果对于一个需要计算出来的结果集(比如用到join),那你实现下看看。为了避免同样的事情做几次你不得不为它提供临时存储,然后操作临时存储表。那样的开销就几倍地增加了。在简单表里做这样的事情,就必须考虑索引,有了合适的索引你的方法1效率可以有几个数量级的提高。

在sqlserver里人家提供了 sp_cursoropen,sp_cursorfetch,sp_cursorclose 操作来执行分页,其他他们已经不是sql 的组成部分了,是几个扩展过程,这也是ado分页的服务端解决方案,对于通用的查询和存储过程,恐怕没有其他在效率上能和它一争高下的解决方案了。
------解决方案--------------------
谢楼上的兄弟
------解决方案--------------------
http://blog.csdn.net/hertcloud/category/281167.aspx
------解决方案--------------------
为什么要把千万行数据拿来分页呀?有这个必要吗?
就算分页了,用户在这么多页中能轻易的定位到自己所要的记录吗?
还不是一样的要靠search。
你完全可以只取top 100或200来分页。
与其讨论这样一个没有意义的分页问题,还不如讨论一下怎么做一个方便的灵活的查询功能!
------解决方案--------------------
GOOD,高人
------解决方案--------------------
mark 咯 。
------解决方案--------------------
模糊查询时索引用不上以致速度太慢怎么处理?
------解决方案--------------------
想办法用上索引。
------解决方案--------------------
上面的话不是太懂呢。

又得查资料看资料了
------解决方案--------------------
UP
------解决方案--------------------
标题取的好大
------解决方案--------------------
> > select @i=@i+1, @id=case when @i <=2000000 then id else @id end from bigt order by id

第一种算法的这种写法可以说明两点:1、认真思考了。2、技术很高,而且严谨。

但是我有一种不严谨的写法

declare @myID int
set @myID = 0

select @myID = id from bigt order by id -- 注意这一行!!


可能你初一看没有理解,其实和必要的结果是一样。当然这种写法是不研究的,不过 MS SQL嘛,微软出的,就是可以应对这种不严谨的写法。


这种算法我也发表过了,里面还有两种算法,也是你这里没有提到的。
http://www.cnblogs.com/jyk/archive/2007/05/31/766908.html