sql server 海量数据速度提升:SQL优化-索引(11) 【转】

12、高效的TOP

  事实上,在查询和提取超大容量的数据集时,影响数据库响应时间的最大因素不是数据查找,而是物理的I/0操作。如:

  select top 10 * from (

  select top 10000 gid,fariqi,title from tgongwen

  where neibuyonghu='办公室'order by gid desc) as a

  order by gid asc

  这条语句,从理论上讲,整条语句的执行时间应该比子句的执行时间长,但事实相反。因为,子句执行后返回的是10000条记录,而整条语句仅返回10条语句,所以影响数据库响应时间最大的因素是物理I/O操作。而限制物理I/O操作此处的最有效方法之一就是使用TOP关键词了。TOP关键词是SQL SERVER中经过系统优化过的一个用来提取前几条或前几个百分比数据的词。经笔者在实践中的应用,发现TOP确实很好用,效率也很高。但这个词在另外一个大型数据库ORACLE中却没有,这不能说不是一个遗憾,虽然在ORACLE中可以用其他方法(如:rownumber)来解决。在以后的关于“实现千万级数据的分页显示存储过程”的讨论中,我们就将用到TOP这个关键词。

  到此为止,我们上面讨论了如何实现从大容量的数据库中快速地查询出您所需要的数据方法。当然,我们介绍的这些方法都是“软”方法,在实践中,我们还要考虑各种“硬”因素,如:网络性能、服务器的性能、操作系统的性能,甚至网卡、交换机等。

  三、实现小数据量和海量数据的通用分页显示存储过程

  建立一个web 应用,分页浏览功能必不可少。这个问题是数据库处理中十分常见的问题。经典的数据分页方法是:ADO 纪录集分页法,也就是利用ADO自带的分页功能(利用游标)来实现分页。但这种分页方法仅适用于较小数据量的情形,因为游标本身有缺点:游标是存放在内存中,很费内存。游标一建立,就将相关的记录锁住,直到取消游标。游标提供了对特定集合中逐行扫描的手段,一般使用游标来逐行遍历数据,根据取出数据条件的不同进行不同的操作。而对于多表和大表中定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等待甚至死机。

  更重要的是,对于非常大的数据模型而言,分页检索时,如果按照传统的每次都加载整个数据源的方法是非常浪费资源的。现在流行的分页方法一般是检索页面大小的块区的数据,而非检索所有的数据,然后单步执行当前行。

  最早较好地实现这种根据页面大小和页码来提取数据的方法大概就是“俄罗斯存储过程”。这个存储过程用了游标,由于游标的局限性,所以这个方法并没有得到大家的普遍认可。

  后来,网上有人改造了此存储过程,下面的存储过程就是结合我们的办公自动化实例写的分页存储过程:  

 

CREATE procedure pagination1

  (@pagesize int, --页面大小,如每页存储20条记录

  @pageindex int --当前页码

  )

  as

  set nocount on //不返回计数,不返回任何结果集

  begin

  declare @indextable table(id int identity(1,1),nid int) --定义表变量

  declare @PageLowerBound int --定义此页的底码

  declare @PageUpperBound int --定义此页的顶码

  set @PageLowerBound=(@pageindex-1)*@pagesize

  set @PageUpperBound=@PageLowerBound+@pagesize

  set rowcount @PageUpperBound

  insert into @indextable(nid) select gid from TGongwen where fariqi > dateadd(day,-365,getdate()) order by fariqi desc

  select O.gid,O.mid,O.title,O.fadanwei,O.fariqi from TGongwen O, @indextable t where O.gid=t.nid

  and t.id>@PageLowerBound and t.id<=@PageUpperBound order by t.id

  end

  set nocount off //返回计数,返回任何结果集

 

  以上存储过程运用了SQL SERVER的最新技术――表变量。应该说这个存储过程也是一个非常优秀的分页存储过程。当然,在这个过程中,您也可以把其中的表变量写成临时表:CREATE TABLE #Temp。但很明显,在SQL SERVER中,用临时表是没有用表变量快的。所以笔者刚开始使用这个存储过程时,感觉非常的不错,速度也比原来的ADO的好。但后来,我又发现了比此方法更好的方法。

文章出处:http://blog.csdn.net/cuizm/article/details/4498988

posted @ 2012-02-22 10:58  zrj531  阅读(559)  评论(0编辑  收藏  举报