可按任意字段排序的百万级数据分页存储过程代码
一直从事大型网站开发,在许多时候都有分页过程。面对百万数据时分页过程显的尤为重要。并且这些需要分页的地方有一个共同的特点,那就是分页但并不是按ID(主键)来排序,而是要求按其他有重复值的列进行排序。比如,其中有一个页面,要列出将近十万条记录按点击进行排序。如果在代码中我们按如下方式进行请求,那速度不会知是如何的慢(数据在十万级上按点击进行排序)
Dim Rs,SqlStr
Set Rs=server.CreateObject("adodb.recordset")
Rs.Open "Select * from Tab_News Order BY Hits desc",Conn,1,1
Rs.pagesize=20
Rs.AbsolutePage=Page
利用上存储过程进行执行效果也令人不太满意!
前面在编程论坛有发表过《百万级数据分页存储过程代码》,但以前所写分页都是必须按ID(主键,不重复)排序的优秀存储过程,但面对按任意字段(可能重复)也是无计可施。
优秀的百万级数据分页存储过程代码(ver2.0) https://bbs.bccn.net/viewthread.php?tid=180627
优秀的百万级数据分页代码(Ver1.0) http://bbs.
上面所发表分页过程都必段是按主键排序
在网上找了许多相关资料查看,终于找到有可以解决的指导方法,下面我把它行文如下,希望对大家有帮助
平台:Win2003+IIS6.0+Sql2000
'---------------------------------------------------------------------
'以下代码为网页代码
Response.Buffer = True
Dim SqlLocalName,SqlUsername,SqlPassword,SqlDatabaseName
Dim ConnStr,Conn
'----------------------------------------------------------------------
'SQL数据库
SqlLocalName ="(local)" '连接IP [ 本地用 (local) 外地用IP ]
SqlUsername ="sa" '数据库用户名
SqlPassword ="XXXXXX" '用户密码
SqlDatabaseName="NewsTable" '数据库名
ConnStr = "Provider=Sqloledb;User ID=" & SqlUsername & "; Password=" & SqlPassword & "; Initial Catalog = " & SqlDatabaseName & "; Data Source=" & SqlLocalName & ";"
On Error Resume Next
Set Conn=Server.CreateObject("ADODB.Connection")
Conn.open ConnStr
If Err Then
err.Clear
Set Conn = Nothing
Response.Write "<div style='font-size:14px;color=#ff0000' align='center'>数据库连接出错,请检查数据库连接字串</div>"
Response.End
End If
'本类进行实例化代码,不将所有可能性条件分页考虑进去。本类仅作参考
'--------------------------------------------------------------------------------------------
'PageNo 当前页;
'PageSizeX 分页大小;
'PageCountX 总页数;
'FieldCount 总记录数;
'StrWhere 查询条件;
'StrOrder 排序语句;
Dim PageNo,PageSizeX,PageCountX,FieldCount,StrWhere,StrOrder
'进行赋值
PageNo=trim(Request.Querystring("PageNo"))
PageSizeX=30 '定义分页大小
if isnumeric(PageNo) or PageNo="" then '如果没有Page值,进行初始化值
PageNo=abs(PageNo)
if PageNo=0 then PageNo=1
else
PageNo=1
end if
'特别注意,StrWhere可以为空,但不能不进行赋值,为空时StrWhere="";StrOrder值不能为空,否则存储过程会出错
StrWhere=" (ClassCode=0101 and Hits>20) "
StrOrder=" Order BY Hits desc "
set recom = server.createobject(")
recom.activeconnection = Conn
= 4
= "GetPageRecord"
recom.Parameters.Append recom.CreateParameter("@StrWhere",202,1,200,StrWhere)
recom.Parameters.Append recom.CreateParameter("@StrOrder",202,1,200,StrOrder)
recom.Parameters.Append recom.CreateParameter("@PageSize",3,1,,PageSizeX)
recom.Parameters.Append recom.CreateParameter("@PageIndex",3,1,,PageNo)
set rs = recom.execute ()
if rs.bof and rs.eof then
set rs=nothing : set recom=nothing : Conn.Close : set Conn=nothing
response.write "没有找到任何记录"
response.end
end if
'显示数据
do while not rs.eof
response.write""&rs("Title")&" 添加时间:"&rs("AddTime")&"<br/>"
rs.movenext
loop
'取得记录总数,计算页数
set rs = rs.NextRecordset
if rs("countx") > 0 then
FieldCount=rs("countx")
else
FieldCount=0
end if
'记算总页数
if (FieldCount mod PageSizeX)>0 then
PageCountX=((FieldCount - (FieldCount mod PageSizeX))/ PageSizeX)+1
else
PageCountX= (FieldCount / PageSizeX)
end if
'进行关闭和释放相关资源
set rs=nothing : set recom=nothing : Conn.Close : set Conn=nothing
'下面是翻页过程,这里我就不在提供了,详细代友请参照前两次版本
'--------------------------------------------------------
'以下代码为存储过程代码
CREATE Procedure GetPageRecord
(
@StrWhere varchar(200),
@StrOrder varchar(200),
@PageSize int,
@PageIndex int
)
AS
/*
名称:GetPagingRecord
作用:按任意字段进行排序分页
作者:天涯听雨(2008-5-22)
声明:此代码你可以无偿使用及转载,但在转载时,请勿移称本文字声明
*/
set nocount on
Begin
Declare @Sqlstr varchar(5000)
Declare @StrCountSQL varchar(1000)
Declare @StrWhereB varchar(100)
Declare @PageLowerBound int
Declare @PageUpperBound int
set @PageLowerBound=(@PageIndex-1)*@PageSize
set @PageUpperBound=@PageLowerBound+@PageSize
Create table #temp
(
RecNo int IDENTITY (1, 1) NOT NULL,
Oldid int
)
set @Sqlstr=" Select ID from Tab_News "
if(@StrWhere<>'')
begin
set @StrWhereB=@StrWhere+" and "
set @StrWhere=" where "+@StrWhere
end
set @Sqlstr="insert into #temp(Oldid) "+@Sqlstr+@StrWhere+@StrOrder
set rowcount @PageUpperBound
exeCute(@Sqlstr)
set @StrCountSQL="Select Count(ID) as countx from Tab_News "+@StrWhereA+""
set @Sqlstr="Select * from Tab_News as a left join #temp as b on (b.Oldid=a.ID) where "+@StrWhereB+" b.RecNo>"+Cast(@PageLowerBound as varchar)+" and b.RecNo<="+Cast(@PageUpperBound as varchar)+@StrOrder
exeCute(@Sqlstr)
exeCute(@StrCountSQL)
end
set nocount off
GO
上面存储过程方法使用了这个临时表方案的存储过程,但由于临时表的建立与丢弃在读写磁盘上耗费太多时间也会导致该存储过程稳定性差,但对比前面我们进行的直接进行读取上速度提高不少,这也叫有所得也必有所失吧。对比下,利用临时表速度提高许多。
面对临时表的所表现出来的性能差,我想应该还会有新的解决此问题,在不久时间,我还会上述方法进行改良!也将会在不久时间在编程论坛中发表。
希望对大家有帮助
如果需要转载,请标明出处,尊重作者的劳动
[[it] 本帖最后由 天涯听雨 于 2008-5-30 11:50 编辑 [/it]]