注册通行证 用户名 密码
  • 文章投稿
  • 博客
  • 论坛
  • 设为首页
  • 加入收藏
jztop.com网络技术
  • 首页
  • | iT新闻
  • | 操作系统
  • | 组网建网
  • | 网络安全
  • | 程序开发
  • | 办公一族
  • | 工具软件
  • | 网页制作
  • | 多媒体制作
  • | 网吧技术
  • | 服务器
  • | 专题教程
Vista | 软件评测 | 系统备份 | 优化 | 进程 | 聊天 | 病毒 | Linux | 黑客 | 防火墙 | 数据库 | Web开发 | Java | Word | 游戏 | 32位开发 | 移动开发
当前位置:首页 > 程序开发 > 微软开发专栏 > ASP.NET 内容正文:ASP.NET中实现大结果集分页研讨

ASP.NET中实现大结果集分页研讨

发布时间:2006-03-13 15:31:04 来源:博客园 网友评论 0 条
  在Web应用程序中,对一个大数据库结果集进行分页已经是一个家喻户晓的问题了。简单的说,你不希望所有的查询数据显示在一个单独的页面中,所以带有分页的显示才是更合适的。虽然在传统的asp里这并不是一个简单的任务,但在asp.net中,DataGrid控件把这一过程简化为只有几行代码。因此,在 asp.net中,分页很简单,但是默认的DataGrid分页事件会从数据库中把所有的记录全部读出来放到asp.net web应用程序中。当你的数据在一百万以上的时候,这将引起严重的性能问题(如果你不相信,你可以在你的应用程序中执行一个查询,然后在任务管理器中查看 aspnet_wp.exe的内存消耗情况)这也就是为什么需要自定义分页行为,这样可以保证仅获得当前页需要的数据记录。

  在网上有很多关于这个问题的文章和帖子,还有一些成熟的解决方案。我写这篇文章的目的不是向你展示一个可以解决一切问题的存储过程,而是出于优化已有方法,同时为你提供一个可供测试的应用程序,这样你就可以根据自己的需要进行开发。

  但是我对目前网上介绍的方法不是很满意。第一,使用了传统的ADO,很明显它们是为“古老”的asp而写的。剩下的一些方法就是SQL Server存储过程,并且其中的一些由于相应时间过慢而无法使用,正如你在文章最后所看到的性能结果一样,但是还是有一些引起了我的注意。

  通用化

  我要对对目前常用的三个方法进行仔细的分析,它们是临时表(TempTable),动态SQL(DynamicSQL)和行计数 (Rowcount)。在下文中,我更愿意把第二个方法称为(升序-降序)Asc-Desc方法。我不认为动态SQL是一个好名字,因为你也可以把动态 SQL逻辑应用于另一个方法中。所有这些存储过程的通病在于,你不得不估计哪些列是你即将要排序的,而不仅仅是估计主键列(PK Columns)而已,这可能导致一系列的问题——对于每个查询来说,你需要通过分页显示,也就是说对于每不同的排序列你必须有许多不同的分页查询,这意味着你要么给每个排序列做不同的存储过程(无论使用哪种分页方法),也么你必须借助动态SQL的帮助把这个功能放在一个存储过程中。这两个方法对于性能有微小的影响,但是它增加了可维护性,特别是当你需要使用这个方法显示不同的查询。因此,在本文中我会尝试使用动态SQL对所有的存储过程进行归纳,但是由于一些原因,我们只能对实现部分的通用性,因此你还是得为复杂查询写独立的存储过程。

  允许包括主键列在内的所有排序字段的第二个问题在于,如果那些列没有作适当的索引,那么这些方法一个也帮不上忙。在所有这些方法中,对于一个分页源必须先做排序,对于大数据表来说,使用非索引列排序的成本是可以忽略不计的。在这种情况下,由于相应时间过长,所有的存储过程都是无法在实际情况下使用的。(相应的时间各有不同,从几秒钟到几分钟不等,这要根据表的大小和所要获得的第一个记录而定)。其他列的索引会带来额外的不希望出现的性能问题,例如如果你每天的导入数据很多,它有可能变得很慢。

  临时表

  首先,我准备先来说一下临时表方法,这是一个广泛被建议使用的解决方案,我在项目中遇到过好几次了。下面让我们来看看这个方法的实质:

CREATE TABLE #Temp(
 ID int IDENTITY PRIMARY KEY,
 PK /*heregoesPKtype*/
)

INSERT INTO #Temp SELECT PK FROM Table ORDER BY SortColumn

SELECT FROM Table JOIN # Temp temp ON Table.PK = temp .PK ORDER BY temp .ID WHERE ID > @StartRow AND ID< @EndRow

  通过把所有的行拷贝到临时表中,我们可以对查询进一步的优化(SELECT TOP EndRow …),但是关键在于最坏情况——一个包含100万记录的表就会产生一个100万条记录的临时表。考虑到这样的情况,再看看上面文章的结果,我决定在我的测试中放弃该方法

  升序-降序

  这个方法在子查询中使用默认排序,在主查询中使用反向排序,原理是这样的:

DECLARE @temp TABLE(
 PK /* PKType */
 NOT NULL PRIMARY
)

INSERT INTO @temp SELECT TOP @PageSize PK FROM
(
 SELECT TOP(@StartRow + @PageSize )
 PK,
 SortColumn /* If sorting column is defferent from the PK,SortColumn must
 be fetched as well,otherwise just the PK is necessary
 */

 ORDER BY SortColumn
 /*
  defaultorder–typicallyASC
 */
)

ORDER BY SortColumn
/*
reversed default order–typicallyDESC
*/

 SELECT FROM Table JOIN @Temp temp ON Table .PK= temp .PK
 ORDER BY SortColumn
 /*
  defaultorder
 */


  行计数

  这个方法的基本逻辑依赖于SQL中的SET ROWCOUNT表达式,这样可以跳过不必要的行并且获得需要的行记录:

DECLARE @Sort /* the type of the sorting column */

SET ROWCOUNT @StartRow

SELECT @Sort=SortColumn FROM Table ORDER BY SortColumn
SET ROWCOUNT @PageSize

SELECT FROM Table WHERE SortColumn >= @Sort ORDER BY SortColumn

  子查询

  还有两个方法也是我考虑过的,他们的来源不同。第一个是众所周知的三角查询(Triple Query)或者说自查询方法,在本文中,我也用一个类似的包含所有其他存储过程的通用逻辑。这里的原理是连接到整个过程中,我对原始代码做了一些缩减,因为recordcount在我的测试中不需要)

SELECT FROM Table WHERE PK IN(
SELECT TOP @PageSize PK FROM Table WHERE PK NOT IN
(
SELECT TOP @StartRow PK FROM Table ORDER BY SortColumn)
ORDER BY SortColumn)
ORDER BY SortColumn

  游标

  在看google讨论组的时候,我找到了最后一个方法。该方法是用了一个服务器端动态游标。许多人试图避免使用游标,因为游标没有关系可言,以及有序性导致其效率不高,但回过头来看,分页其实是一个有序的任务,无论你使用哪种方法,你都必须回到开始行记录。在之前的方法中,先选择所有在开始记录之前的所有行,加上需要的行记录,然后删除所有之前的行。动态游标有一个FETCH RELATIVE选项可以完成魔法般的跳转。基本的逻辑如下:

DECLARE @PK /* PKType */

DECLARE @tblPK

TABLE(
 PK /*PKType*/ NOT NULL PRIMARY KEY
)

DECLARE PagingCursor CURSOR DYNAMICREAD_ONLY FOR
SELECT @PK FROM Table ORDER BY SortColumn

OPEN PagingCursor
FETCH RELATIVE @StartRow FROM PagingCursor INTO @PK

WHILE @PageSize>0 AND @@FETCH_STATUS =0
BEGIN
 INSERT @tblPK(PK) VALUES(@PK)
 FETCH NEXT FROM PagingCursor INTO @PK
 SET @PageSize = @PageSize - 1
END

CLOSE
 PagingCursor
DEALLOCATE
 PagingCursor

SELECT FROM Table JOIN @tblPK temp ON Table .PK= temp .PK
ORDER BY SortColumn

相关文章
  • ASP.NET1.0升级ASP.NET2.0的问题总结
  • ASP.NET2.0中Gridview中数据操作技巧
  • ASP.NET2.0导航功能之配置会员和角色
  • 在ASP.NET程序中实现语音合成
  • ASP.NET编程入门随想之宽容
【评论】【收藏本文】【打印】【关闭】
上一篇文章:ASP.NET1.0升级ASP.NET2.0的问题总结
下一篇文章:ASP.NET 2.0中实现跨页面提交
讨论区
查看
已有 0 位对此新闻感兴趣的网友发表了看法
匿名发表
注册通行证 登陆
图文阅读推荐
推荐阅讯
  • 用ASP.NET实现文件的在线压缩和解压缩
  • ASP.NET入门随想之金庸群“粒”传
  • 迁移你的Web页面到ASP.NET AJAX 1.0
  • ASP.NET2.0服务器控件之创建复杂属性
  • 当ASP.NET撞上JSF之应用程序的国际化
  • ASP.NET+AJAX解决网页打开等待问题
  • ASP.NET 2.0服务器控件开发之控件样式
  • ASP.NET Atlas简单控件介绍之界面控件
  • ASP.NET 2.0打造购物车和支付系统之二
  • 如何充分利用ASP.NET 2.0预编译
阅读排行
  • 1.用ASP.NET 2.0设计网络在线投票系统
  • 2.在ASP.Net 2.0中实现多语言界面的方法
  • 3.轻松加密ASP.NET 2.0 Web程序配置信息
  • 4.在ASP.NET中使用AJAX的简单方法
  • 5..NET 2.0中的企业库异常处理块简述
  • 6.面向.NET开发人员的Ajax 技术平台策略
  • 7.揭开ASP.NET中Cookie编程的奥秘
  • 8.ASP.NET2.0服务器控件之创建自定义控件
  • 9.ASP.NET2.0中Gridview中数据操作技巧
  • 10.ASP.NET 2.0发送电子邮件全面剖析之二
专题教程
  • 大话G游 专题:手机病毒揭密
  • ARP攻击防范与解决方案 路由故障处理手册
  • Picasa中文版_Picasa教程 专题:清除流氓软件
  • Firefox专题 seo搜索引擎优化专区
  • 重装Windows必知的事情 装机之必备软件大行动
病毒专杀栏
  • 杀毒软件反被病毒杀 连"救命"都不能喊
  • 金山ARP防火墙
  • 还原卡神话破灭“机器狗”病毒来势汹汹
  • cctv经济半小时:你的手机现在安全吗?
  • 新挂马方式开始流行 ARP挂马称雄局域网
  • 木马和病毒清除的通用解法
  • IP地址不再冲突 查找ARP攻击者元凶
  • 教你几招识别和防御Web网页木马
  • 分析:封杀BT只是暂时的止痛药
  • QQ爆危险漏洞,“QQ游戏邀请大盗”邀请你玩病
关于我们 | 诚聘英才 | 联系我们 | 版权声明 | 网站大事 | 网站地图 | 意见建议
CopyRight 2005-2007 Jztop.Com 版权所有 未经许可 请勿转载