随笔-19  评论-78  文章-0  trackbacks-0
这个存储过程执行的速度还不错.500W速度分页只要2秒,任何页数
可是有点问题就是,如果排序不是主键,ID,那么分页就会出错,不知道各位有什么好个意见,修改一下
-------------------------------------------------------


SQL code
create procedure SqlDataPaging @tbName varchar(255), --表名 @tbFields varchar(1000), --返回字段 @OrderField varchar(255), --排序的字段名 @PageSize int, --页尺寸 @PageIndex int, --页码 @OrderType bit, --排序类型,1是升序,0是降序 @strWhere varchar(1500), --查询条件 @Total int output --返回总记录数 as declare @strSql varchar(5000) --主语句 declare @strOrder varchar(200) --排序 declare @strSqlCount nvarchar(500)--查询记录总数主语句 declare @strtemp varchar(50) --排序附加语句 --------------排序-----------------1是降序,0未升序 if @OrderType !=0 begin set @strtemp= '>(select max(' set @strOrder='order by ' + @OrderField + ' asc ' end else begin set @strtemp= '<(select min(' set @strOrder='order by '+ @OrderField + ' desc' end --------------总记录数--------------- if @strWhere !='' begin set @strSqlCount='Select @TotalCout=count(*) from ' + @tbName + 'where '+ @strWhere end else begin set @strSqlCount='Select @TotalCout=count(*) from ' + @tbName end --------------如果是第一页------------ if @PageIndex =1 begin if @strWhere !='' begin set @strSql = 'Select top' +str(@PageSize)+ ' ' + @tbFields + ' from '+ @tbName +' where ' + @strWhere + ' ' + @strOrder end else begin set @strSql = 'Select top' +str(@PageSize)+ ' ' + @tbFields + ' from '+ @tbName + ' ' + @strOrder end end else begin if @strWhere !='' begin set @strSql='Select top ' +str(@PageSize) + ' ' + @tbFields +' from ' + @tbName + ' where '+@OrderField +' ' + @strtemp+ ' ' +@OrderField+ ') from (select top' +str((@PageIndex-1)*@PageSize) + ' '+@OrderField +' from '+@tbName + @strWhere+ ' '+ @strOrder +') as tb)'+ @strOrder end else begin set @strSql='Select top ' + str(@PageSize) + ' ' + @tbFields +' from ' + @tbName + ' where '+@OrderField + ' ' + @strtemp+ ' ' +@OrderField+ ') from (select top' +str((@PageIndex-1)*@PageSize) + ' '+@OrderField +' from '+@tbName + ' '+ @strOrder +') as tb)'+ @strOrder end end exec sp_executesql @strSqlCount,N'@TotalCout int output',@Total output exec(@strSql)
Tag标签: .net,asp.net,分頁
posted on 2008-05-03 13:14 Harlan--- 阅读(6027) 评论(40)  编辑 收藏 网摘 所属分类: .NetAsp.Net

评论:
#1楼 2008-05-03 13:20 | 搜索[未注册用户]
我们在数据4000万的时候,实现分页查询也不到1秒,2秒用户受不了
  回复  引用    
#2楼 2008-05-03 13:30 | Jeffrey Zhao      
动辄说海量海量的,进来一看还是普通的拼接字符串的方式,一点特点也没有
  回复  引用  查看    
#3楼 2008-05-03 13:47 | 搞IT的狐狸      
另外在 SQL里 != 是错误的用法 请用 <>
  回复  引用  查看    
#4楼 2008-05-03 13:49 | zzz[未注册用户]
500w一个count(*)都要好几秒了,还2秒。。。没用。。。
  回复  引用    
#5楼 2008-05-03 14:00 | 李战      
http://www.cnblogs.com/Emoticons/yoyocici/223852199.gif" alt="" />路过,学习
  回复  引用  查看    
#6楼 2008-05-03 14:07 | Joyaspx      
这个分页方法已经很老了,首先是他都是用拼接字符串的形式来制造sql语句的,这样在调用这个存储过程之前还得准备好各种条件。
其次是用top方法分页并不是一个可取的方法,可以考虑用row_number()分页,对排序并没有标识字段的要求。

  回复  引用  查看    
#7楼 2008-05-03 14:14 | 年轻活力      
--引用--------------------------------------------------
Joyaspx: 这个分页方法已经很老了,首先是他都是用拼接字符串的形式来制造sql语句的,这样在调用这个存储过程之前还得准备好各种条件。
其次是用top方法分页并不是一个可取的方法,可以考虑用row_number()分页,对排序并没有标识字段的要求。
--------------------------------------------------------
标不标识这只是一部分了,主要是要有一个主键,或唯一标识,用row-number的结果也是一样。
有了唯一标识,加上索引,效率不会比row-number差吧

  回复  引用  查看    
#8楼 2008-05-03 14:16 | kiler      
分页的问题还是要转变一下观念啊,问题在于要不要对所有的500w条数据分页,都显示出来客户看得了吗,他会从头点到尾吗,还不就是看前几页,想看后面的数据,设定排序条件反序排一下还是前几页,只对前5000条进行分页不行吗?
  回复  引用  查看    
#9楼 2008-05-03 14:22 | Ext[未注册用户]
500W就是海量?
  回复  引用    
#10楼 2008-05-03 14:23 | Ext[未注册用户]
再有 N久前 这代码就是别人发过的了
  回复  引用    
#11楼 2008-05-03 15:02 | zfphere      
cnblogs 没有创新了?
  回复  引用  查看    
#12楼 2008-05-03 15:08 | 布尔      
sqlserver2005已经引入了新的处理办法,升级以下吧
另外,如果想简单建议使用rowcount呵呵

  回复  引用  查看    
#13楼 2008-05-03 15:44 | ddr888      
最鄙视那些直说别人的如何如何差又不放自己的代码人。
如果觉得别人如何差,把自己好的放上来啊。

  回复  引用  查看    
#14楼 2008-05-03 16:11 | Angel Lucifer      
看来有必要讨论一下这个话题,呵呵。
  回复  引用  查看    
#15楼 2008-05-03 16:24 | 路人Z[未注册用户]
你们都忽略机器性能的可比性.
  回复  引用    
#17楼 2008-05-03 17:19 | 苏州SEO[未注册用户]
海量存储我认为应该在百万以上。
  回复  引用    
#18楼 2008-05-03 18:03 | 金色海洋(jyk)      
不知道lz有没有看到
http://www.cnblogs.com/jyk/archive/2008/04/29/1175808.html" target="_new">http://www.cnblogs.com/jyk/archive/2008/04/29/1175808.html

http://www.cnblogs.com/jyk/archive/2007/05/31/766908.html" target="_new">http://www.cnblogs.com/jyk/archive/2007/05/31/766908.html

可以参考一下,这是一个分页控件,有源码,还有分页算法。

500w 数据 count(1) 一下,不会超过 800毫秒的。

我的分页控件

cpu:xp3000+ 单核
内存:DDR2 1G
硬盘:串口

测试用数据库:SQL Server2000 里的 Northwind 数据库里的 Products 表,就是自带的那个。
显示数据的控件:DataGrid 自动填充字段的方式。

记录数:2523136条。
一页显示5条记录。


//分页算法1 单字段排序,且排序字段是聚集索引。
//1000 页以内 15毫秒
//10000页以内 30毫秒
//50000页以内 100多毫秒
//100000页以内 200多毫秒
//最后几页 第一次跳转到 4秒多
//最后几页 连续向前翻页 1秒156毫秒

//页号大范围跳转的时候需要的时间比较长,但是也小于1秒,同时SQL Server 占用的内存有所增加 120M。最后几页时达到320M

===================================================================
以下是多排序字段的分页情况,排序字段是 UnitPrice,ProductID

//分页算法2 无索引 首页 8秒187毫秒 。
//10 页以内 2秒812毫秒
//速度太慢下面的就不测试了

//分页2 非聚集索引 UnitPrice 首页 468毫秒
//10 页以内 2秒671毫秒
//速度太慢下面的就不测试了


//分页算法2 非聚集索引 UnitPrice,ProductID 首页 500毫秒
//10 页以内 2秒796毫秒
//100页以内 4秒796毫秒
//速度太慢下面的就不测试了


//分页算法2 非聚集索引 UnitPrice,ProductID desc 首页 500毫秒
//10 页以内 0-15毫秒
//100页以内 15-46毫秒
//1000页以内 31-62毫秒
//10000页以内 100毫秒左右
//50000页以内 400-500毫秒
//100000页以内 900毫秒左右
//最后几页 第一次跳转到 4秒421毫秒
//最后几页 连续向前翻页 4秒375毫秒

//页号大范围跳转的时候需要的时间比较长,但是也小于1秒,
//这回SQL Server 占用的内存增加幅度不大 120M左右


  回复  引用  查看    
#19楼 2008-05-03 18:59 | 扬[未注册用户]
这个分页算我现在用着!不过就会出你非唯一建排序而导致错误的结果的情况。郁闷。
  回复  引用    
#20楼 2008-05-03 19:27 | csulonely      
尊重楼主的努力,希望大家评论时语言温和点,博客园是个交朋友的地方,大家要共同营造和谐的气氛!
  回复  引用  查看    
#21楼 2008-05-03 19:27 | 郭树灿[未注册用户]
添加与删除用一个表统计总数后再分页在海量数据必须这么做,你那么做只对一半--读取总记录数
SET ROWCOUNT 1
SELECT @Count = Count
FROM BaseInfo_TheEmployee_Count
if @@ROWCOUNT <> 1
begin
set @Return = -6
return -6
end
if @@error <> 0
begin
set @Return = -7
return -7
end
--计算总页数
set @OutPage = dbo.CountPage(@Count, @SetPageRows)
--页码大于总页码侧修饰为数据总数计算分页页码
if @SetPage > @OutPage set @SetPage = @OutPage
--计算对后一页余数值
set @PageMin = dbo.CountTopMin(@Count,@SetPageRows,@SetPage,@OutPage)
--计算页码
set @PageMax = (@SetPage * @SetPageRows)
--读取员工信息与一寸相片与身份证复印件
if @ShowPhoto = 1 and @ShowIDCardPhoto = 1
if @Order = 1
begin
--重新设定读取行数
SET ROWCOUNT @PageMin
SELECT TOP (@PageMin) TheEmployeeID, TheEmployeeName, CreatedDate, Auditing,
UniqueNumber, Sex, Tel, Number, EnterDutyDate, DateOfBirth,
EducateTheBackgroundTypeID, HouseholdRegister, IDCard, TheEmployeeTypeID,
MobilePhone, StandbyTel, Address, State, Email, FixedWage, ZipCode, Remark,
SalaryAccountNumber, DepartmentTypeID, Piecework, BusinessMember, HeadshipTypeID,
DimissionState, IDCardPhoto, IDCardPhotoImageType, Photo, PhotoImageType
FROM (SELECT TOP (@PageMax) TheEmployeeID, TheEmployeeName, CreatedDate, Auditing,
UniqueNumber, Sex, Tel, Number, EnterDutyDate, DateOfBirth,
EducateTheBackgroundTypeID, HouseholdRegister, IDCard,
TheEmployeeTypeID, MobilePhone, StandbyTel, Address, State, Email,
FixedWage, ZipCode, Remark, SalaryAccountNumber, DepartmentTypeID,
Piecework, BusinessMember, HeadshipTypeID, DimissionState, IDCardPhoto,
IDCardPhotoImageType, Photo, PhotoImageType
FROM (SELECT BaseInfo_TheEmployee.TheEmployeeID,
BaseInfo_TheEmployee.TheEmployeeName,
BaseInfo_TheEmployee.CreatedDate, BaseInfo_TheEmployee.Auditing,
BaseInfo_TheEmployee.UniqueNumber, BaseInfo_TheEmployee.Sex,
BaseInfo_TheEmployee.Tel, BaseInfo_TheEmployee.Number,
BaseInfo_TheEmployee.EnterDutyDate,
BaseInfo_TheEmployee.DateOfBirth,
BaseInfo_TheEmployee.EducateTheBackgroundTypeID,
BaseInfo_TheEmployee.HouseholdRegister,
BaseInfo_TheEmployee.IDCard,
BaseInfo_TheEmployee.TheEmployeeTypeID,
BaseInfo_TheEmployee.MobilePhone,
BaseInfo_TheEmployee.StandbyTel, BaseInfo_TheEmployee.Address,
BaseInfo_TheEmployee.State, BaseInfo_TheEmployee.Email,
BaseInfo_TheEmployee.FixedWage, BaseInfo_TheEmployee.ZipCode,
BaseInfo_TheEmployee.Remark,
BaseInfo_TheEmployee.SalaryAccountNumber,
BaseInfo_TheEmployee.DepartmentTypeID,
BaseInfo_TheEmployee.Piecework,
BaseInfo_TheEmployee.BusinessMember,
BaseInfo_TheEmployee.HeadshipTypeID,
BaseInfo_TheEmployee.DimissionState,
BaseInfo_TheEmployee_IDCardPhoto.IDCardPhoto,
BaseInfo_TheEmployee_IDCardPhoto.IDCardPhotoImageType,
BaseInfo_TheEmployee_Photo.Photo,
BaseInfo_TheEmployee_Photo.PhotoImageType
FROM BaseInfo_TheEmployee INNER JOIN
BaseInfo_TheEmployee_IDCardPhoto ON
BaseInfo_TheEmployee.TheEmployeeID = BaseInfo_TheEmployee_IDCardPhoto.TheEmployeeID
INNER JOIN
BaseInfo_TheEmployee_Photo ON
BaseInfo_TheEmployee.TheEmployeeID = BaseInfo_TheEmployee_Photo.TheEmployeeID)
AS a
ORDER BY TheEmployeeID) AS b
ORDER BY TheEmployeeID DESC
if @@ROWCOUNT <> @PageMin
begin
set @Return = -8
return -8
end
if @@error <> 0
begin
set @Return = -9
return -9
end
set @Return = @PageMin
return @PageMin
end

  回复  引用    
#22楼 2008-05-03 19:57 | 曲滨*銘龘鶽      
SQL server 2000 本来在在设计上对分页类操作就是有缺陷的怎么也不行
SQL server 2005 虽然加了 row_number() 不过使用起来没有其他数据库如oracle 哪么方便,不过相对的容易很多;

不过 SQL server 嵌套查询这里做的不好,
比如子查询不能排序等
使得好多复杂查询很难做通用的分页查询。

期待 2008 有好转

  回复  引用  查看    
#23楼 2008-05-03 21:25 | 留恋星空      
有更好的方式么?如果非得是SQL 2000?
  回复  引用  查看    
#24楼 2008-05-03 22:32 | NormRen[未注册用户]
--引用--------------------------------------------------
kiler: 分页的问题还是要转变一下观念啊,问题在于要不要对所有的500w条数据分页,都显示出来客户看得了吗,他会从头点到尾吗,还不就是看前几页,想看后面的数据,设定排序条件反序排一下还是前几页,只对前5000条进行分页不行吗?
--------------------------------------------------------
赞同这个做法,淘宝也是只给出了前100页的数据。

  回复  引用    
#25楼 2008-05-04 09:04 | dudubeibei      
我觉得不考虑查询条件不同的分页SP的效率应该差不了多少,如果加入各种各样的查询条件,差别可能就比较大了。我觉得根据特定的表写特定的分页SP,效率可能会好些。
  回复  引用  查看    
#26楼 2008-05-04 10:06 | nicye      
--引用--------------------------------------------------
搞IT的狐狸: 另外在 SQL里 != 是错误的用法 请用 &lt;&gt;
--------------------------------------------------------
好像 mssql 2005 可以

  回复  引用  查看    
#27楼 2008-05-04 10:51 | laifangsong      
楼主,我的分页存储过程和你的类似,但没要求排序的字段必须是主键




/****** 对象: 存储过程 dbo.sp_Paging 脚本日期: 2007-11-27 9:43:17 ******/




/****** 对象: 存储过程 dbo.sp_Paging 脚本日期: 2007-4-27 13:19:03 ******/

/*
分页存储过程(来源于网络,经过修改以适应多表联合查询)

注意:该存储过程和和网络上其他分页存储过程一样,存在经典的SQL注入漏洞; 不论在asp/asp.net等中调用时,
都要把 @strWhere参数中的非法字符(逗号过滤掉)
*/

CREATE PROCEDURE sp_Paging
@tblName varchar(255) , -- 表名
@strGetFields varchar(1000) = '*', -- 需要返回的列
@fldName varchar(255)='', -- 主关键字字段名
@orderfield varchar(255)='', -- 排序的字段名
@pageSize int = 10, -- 页尺寸
@pageIndex int = 1, -- 页码
@recordCount int = 0 output, -- 返回记录总数
@pageCount int = 0 output, --分页总数
@orderType int = 0, -- 设置排序类型, 非 0 值则降序
@strWhere varchar(1500) = '' -- 查询条件 (注意: 不要加 where)
AS
declare @strSQL nvarchar(3000) -- 主语句
declare @strTmp varchar(110) -- 临时变量
declare @strOrder varchar(400) -- 排序类型

begin
if @strWhere !=''
set @strSQL = 'select @recordCount = count(*) from ' + @tblName + ' where '+@strWhere
else
set @strSQL = 'select @recordCount = count(*) from ' + @tblName
end

exec sp_executesql @strSQL,N'@recordCount int out ',@recordCount out

if @recordCount % @pageSize = 0
set @pageCount = @recordCount / @pageSize
else
set @pageCount = @recordCount / @pageSize + 1
--以上代码的意思是计算出记录是总数和求出总共的页数

begin
if @orderType != 0
begin
set @strTmp = '<(select min'
set @strOrder = ' order by ' + @orderfield +' desc'
--如果@orderType不是0,就执行降序,这句很重要!
end
else
begin
set @strTmp = '>(select max'
set @strOrder = ' order by ' + @orderfield +' asc'
end

if @pageIndex = 1
begin
if @strWhere != ''

set @strSQL = 'select top ' + str(@pageSize) +' '+@strGetFields+ ' from ' + @tblName + ' where ' + @strWhere + ' ' + @strOrder
else

set @strSQL = 'select top ' + str(@pageSize) +' '+@strGetFields+ ' from '+ @tblName + ' '+ @strOrder
--如果是第一页就执行以上代码,这样会加快执行速度
end
else
begin
if @strWhere != ''
set @strSQL = 'select top ' + str(@pageSize) +' '+@strGetFields+ ' from '
+ @tblName + ' where ' + @fldName + '' + @strTmp + '('
+ substring(@fldName, charindex('.',@fldName)+1, len(@fldName)) + ') from (select top ' + str((@pageIndex-1)*@pageSize) + ' '
+ @fldName + ' from ' + @tblName + ' where ' + @strWhere + ' '
+ @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder
else
set @strSQL = 'select top ' + str(@pageSize) +' '+@strGetFields+ ' from '
+ @tblName + ' where ' + @fldName + '' + @strTmp + '('
+ substring(@fldName, charindex('.',@fldName)+1, len(@fldName)) + ') from (select top ' + str((@pageIndex-1)*@pageSize) + ' '
+ @fldName + '  from ' + @tblName + '' + @strOrder + ') as tblTmp)'
+ @strOrder
end
end
print @strSQL
exec sp_executesql @strSQL

GO

  回复  引用  查看    
#28楼 2008-05-04 11:06 | sunrisex[未注册用户]
不知道把500w数据分页来做什么?给人看?给电脑看? 还是用来做什么? 谁会这样看数据? 谁/那一类人有这个需求? 或在什么情况下会用得上? 你做这个功能的给谁用啊?
  回复  引用    
#29楼 2008-05-04 12:17 | nicye      
top 10000,多余的查出来也没人看
  回复  引用  查看    
#30楼 2008-05-04 13:31 | 潜水员      
我也来晒晒我目前用到的两个存储过程:http://www.cnblogs.com/zhengyulu-2008/articles/1095534.html" target="_new">http://www.cnblogs.com/zhengyulu-2008/articles/1095534.html
  回复  引用  查看    
#31楼 2008-05-04 13:42 | 倒霉孩子[未注册用户]
都是垃圾,没事爱找别人的错,如果行的话,就把代码穿上去分享一下
  回复  引用    
#32楼 2008-05-04 17:24 | badnewfish      
我没做过这样的应用,但是我笨笨的一想,每次取一页的数据就可以了!
点“下一页”时再去取下一页的!
呵呵!

  回复  引用  查看    
#33楼 2008-05-04 20:17 | 蜀山雪狼      
--引用--------------------------------------------------
badnewfish: 我没做过这样的应用,但是我笨笨的一想,每次取一页的数据就可以了!
点“下一页”时再去取下一页的!
呵呵!
--------------------------------------------------------
你太有才了。

  回复  引用  查看    
#34楼 2008-05-04 20:51 | 没剑      
2s太慢了,呵呵
  回复  引用  查看    
#35楼 2008-05-05 09:46 | CODE      
我收一下了
  回复  引用  查看    
#36楼 2008-06-02 14:23 | kevinlzf[未注册用户]
请第一楼的,还有 "没剑"这位仁兄把你们的海量数据分页方法贴出来啊,别老是在这里忽悠.支持楼主
  回复  引用    
#37楼 2008-06-06 00:14 | 赖文华(SWPU小赖)      
谢谢楼主分享,如果有朋友有更好的方法,请分享!
  回复  引用  查看    
#38楼 2008-06-07 23:44 | zang1219[未注册用户]
强烈鄙视那些只说自己的如何好的,不贴代码的。
楼主的这个不错。
在大的项目也没有全部显示出来的。

  回复  引用    
#39楼 2008-11-08 17:25 | zyming[未注册用户]
@蜀山雪狼
真是个聪明的人啊!

  回复  引用    
#40楼 2009-01-14 21:55 | 不清楚[未注册用户]
不知道当数据库中有大量重复的数据的时候,且排序字段偏偏又要以重复字段为准是:
点到下一页的时候是不是没反映,老是在那一页

  回复  引用    



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1177760




相关文章:

相关链接: