数据量过大时数据库操作的处理[5]

[入库:2005年8月18日] [更新:2007年3月24日]

本文简介:选择自 cuijian_ok 的 blog

 @id varchar(255),       --需要排序的不重复的id号
 @sort varchar(255)      --排序字段及规则
)
as

declare @str nvarchar(4000)

set @str='select   top '+cast(@recsperpage as varchar(20))+' * from ('+@sql+') t where t.'+@id+'not in
(select   top '+cast((@recsperpage*(@page-1)) as varchar(20))+' '+@id+' from ('+@sql+') t9 order by '+@sort+') order by '+@sort

print @str

exec sp_executesql @str
go

其实,以上语句可以简化为:

select top 页大小 *

from table1

where (id not in

          (select top 页大小*页数 id

         from 表

         order by id))

order by id

但这个存储过程有一个致命的缺点,就是它含有not in字样。虽然我可以把它改造为:

select top 页大小 *

from table1

where not exists

(select * from (select top (页大小*页数) * from table1 order by id) b where b.id=a.id )

order by id

即,用not exists来代替not in,但我们前面已经谈过了,二者的执行效率实际上是没有区别的。

既便如此,用top 结合not in的这个方法还是比用游标要来得快一些。

虽然用not exists并不能挽救上个存储过程的效率,但使用sql server中的top关键字却是一个非常明智的选择。因为分页优化的最终目的就是避免产生过大的记录集,而我们在前面也已经提到了top的优势,通过top 即可实现对数据量的控制。

在分页算法中,影响我们查询速度的关键因素有两点:top和not in。top可以提高我们的查询速度,而not in会减慢我们的查询速度,所以要提高我们整个分页算法的速度,就要彻底改造not in,同其他方法来替代它。

我们知道,几乎任何字段,我们都可以通过max(字段)或min(字段)来提取某个字段中的最大或最小值,所以如果这个字段不重复,那么就可以利用这些不重复的字段的max或min作为分水岭,使其成为分页算法中分开每页的参照物。在这里,我们可以用操作符“>”或“<”号来完成这个使命,使查询语句符合sarg形式。如:

select top 10 * from table1 where id>200

于是就有了如下分页方案:

select top 页大小 *

from table1

where id>

      (select max (id) from

      (select top ((页码-1)*页大小) id from table1 order by id) as t

       )    

  order by id

在选择即不重复值,又容易分辨大小的列时,我们通常会选择主键。下表列出了笔者用有着1000万数据的办公自动化系统中的表,在以gid(gid是主键,但并不是聚集索引。)为排序列、提取gid,fariqi,title字段,分别以第1、10、100、500、1000、1万、10万、25万、50万页为例,测试以上三种分页方案的执行速度:(单位:毫秒)

页  码
 方案1
 方案2
 方案3
 
1
 60
 30
 76
 
10
 46
 16
 63
 
100
 1076
 720
 130
 
500
 540
 12943
 83
 
1000
 17110
 470
 250
 
1万
 24796
 4500
 140
 
10万
 38326
 42283
 1553
 
25万
 28140
 128720
 2330
 
50万
 121686
 127846
 7168

本文关键:数据量过大时数据库操作的处理
  相关方案
Google
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top