大家来讨论讨论 -> 最佳的数据库分页方法
cwsj 2002-09-12 07:00:32 大家来讨论讨论 -> 最佳的数据库分页方法
下面的文章说:
客户端传递一个页码过去,然后SQLServer直接通过一次查询就生成所需的一页的记录集,并且以一个纪录集的形式返回给客户端,是最佳的分页方法。但是微软示范的分页方法是用只读快速游标取出某页的记录集,而不是在procedure中分页,难道微软的方法是低效率的?不明白。
最简单的方法是哪位高手能测试比较一下,得出一个结果。
转自:http://club.topdigi.com.cn/tech/shtm/sql/35.shtm
一:一个老生常谈的问题。
我们知道,记录集分页是数据库处理中十分常见的问题。而当我们设计到网络数据库,就是说要考虑传输带宽问题时,分页问题就每每困扰着每一个数据库程序设计人员。
二:分页问题的解决方案汇总
说起解决的方案,每个数据库设计人员可能都会举出许多方法。但细分后,可以归为三类。一:Ado纪录集分页、二:专储记录集分页、三、数据库游标分页。
一:著名的ADO纪录集分页。
说到著名,因为这个可能是最简单和常见的分页方法了。(可能也是用的最多的)就是利用ADO自带的分页功能来实现分页。
二:转储纪录集分页。
这种方法诞生于网络时代,就是利用服务器端的强大处理过程,先将目标数据库存到一个临时的数据库里,并且加上一个自增字段来进行划分页面,最后将所需固定数目的纪录集传回。
第三种方法:服务器端游表选取纪录集的办法。
这种办法属于很有争论的办法。
它主要是用服务器端的游表选取纪录集,然后一次返回,也就是返回多个纪录集,每个纪录集就有一个纪录。然后用Recordset.nextrecord的方法来输出每一个纪录集。
国外许多网站对此进行过考证,因为第一:Recordset.nextrecord具有这种方法的ADO.游表不是最快的火线游表,第二,许多人认为采用recordset.nextrecord方法输出时其实等于和服务器端交互了一次,所以这种方法属于那种当许多人并发访问数据库时,能导致数据库访问量成倍增。。。
列举程序:(作者:bigeagle)
if exists(select * from sysobjects where ID = object_id("up_TopicList"))
drop proc up_TopicList
go
create proc up_TopicList
@a_ForumID int , @a_intDays int , @a_intPageNo int , @a_intPageSize tinyint
as
declare @m_intRecordNumber int
declare @m_intStartRecord int
select @m_intRecordNumber = @a_intPageSize * @a_intPageNo
select @m_intStartRecord = @a_intPageSize * (@a_intPageNo - 1) + 1
if @a_intDays = 0 --如果不限定天数
begin
/*求符合条件记录数*/
select "RecordCount" = count(*)
from BBS where Layer=1 and ForumID = @a_ForumID
/*输出纪录*/
/*首先定义可滚动光标*/
set rowcount @m_intRecordNumber
declare m_curTemp Scroll cursor
for
select a.ID ,a.Title , d.UserName , a.FaceID ,
'ContentSize' = datalength(a.Content) ,
'TotalChilds' = (select sum(TotalChilds)
from BBS as b
where a.RootID = b.RootID) ,
'LastReplyTime' = (select max(PostTime)
from BBS as c
where a.RootID = c.RootID)
from BBS as a
join BBSUser as d on a.UserID = d.ID
where Layer=1 and ForumID = @a_ForumID
order by RootID desc , Layer , PostTime
open m_curTemp
fetch absolute @m_intStartRecord from m_curTemp
while @@fetch_status = 0
fetch next from m_curTemp
set rowcount 0
/*清场*/
CLOSE m_curTemp
DEALLOCATE m_curTemp
end
else --如果限定天数
begin
/*求符合条件记录数*/
select "RecordCount" = count(*)
from BBS where Layer=1 and ForumID = @a_ForumID
and dateadd(day , @a_intDays , PostTime) > getdate()
/*输出纪录*/
/*首先定义可滚动光标*/
set rowcount @m_intRecordNumber
declare m_curTemp Scroll cursor
for
select a.ID ,a.Title , d.UserName , a.FaceID ,
'ContentSize' = datalength(a.Content) ,
'TotalChilds' = (select sum(TotalChilds)
from BBS as b
where a.RootID = b.RootID) ,
'LastReplyTime' = (select max(PostTime)
from BBS as c
where a.RootID = c.RootID)
from BBS as a
join BBSUser as d on a.UserID = d.ID
where Layer=1 and ForumID = @a_ForumID
and dateadd(day , @a_intDays , PostTime) > getdate()
order by RootID desc , Layer , PostTime
open m_curTemp
fetch absolute @m_intStartRecord from m_curTemp
while @@fetch_status = 0
fetch next from m_curTemp
set rowcount 0
/*清场*/
CLOSE m_curTemp
DEALLOCATE m_curTemp
end
go
注:若在asp中调用存储过程的command