利用自定义分页技术提高数据库性能

孟宪会

2002-11-11 14:28:17


Web应用程序是显示数据库中数据的一个非常好的方法,通过它,你可以把业务复杂,并有访问和安全规则的数据库数据以一种简单、直观的方式向用户提供查询和更新的功能。用户判断数据库应用程序一个很常用的标准就是

处理数据的快慢。许多Web页面都向用户提供了多种可搜索的列表显示来有效地定位记录的位置,一个比较简单而且常用的例子就是在线图书查询系统,它允许用户可以按作者,按书名或者按主题来检索图书信息。

ASP.NET提供了一个DataGrid控件可以比以前的ASP方便地创建创建数据列表,DataGrid控件除了内建的数据表现和方法之外,还允许用户自己定义表现形式。分页技术为用户可管理的数据查找提供方便。DataGrid内建的分页技术很容易实现,但数据量很大时,它的方便性是以牺牲性能为代价的。下面,我们就看看如何通过自定义的分页方法来实现快速处理大量数据的结果集的办法。我们这里讨论的方法比DataGrid的默认分页方法是快速和更加有效的,这是因为每次请求不需要把全部的数据结果发送到Web服务器。相反,它只需要发送每个页面需要的那些数据集。例如:如果一个用户只要求100个页面中每页显示25条记录的第4页的结果集,服务器只需要发送第75-100行的数据即可,而不是1-1000行的完全数据。默认的传送方式如图1所示:

从图中可以看出,DataGrid的内建分页方法是效率不高的,每次请求都必须把整个查询结果发送给Web服务器,Web服务器再把数据分成相应的页面。利用DataGrid的内建的分页方法尽管是很简单的,但是,由于Web应用的无序性特征,一个用户每次从一个页面转向另外一个页面时,DataGrid对象都被销毁并重新创建,这就意味着数据库服务器每次都必须发送全部的结果集。

自定义的分页方法只返回所要检索的那些结果集,如下图2所示:

从上面的图中可以看到,数据库每次只需要返回所要显示的数据记录。首先,我们在数据库中建立一个存储过程,并有两个输入参数,分别是要返回数据的第一条记录数和最后一条记录数,在SQL Server7.0以上的版本中,都有一个top关键字限制返回到结果集中的前多少条记录数,然而不幸的是,没有一个方法可以返回中间一部分的数据,例如第75条记录到100条记录的数据。Oracle中有一个rownum()的扩展函数可以返回中间的记录,比如:"select * form Authors where Author_Last_Name = 'Anderson' and rownum() >=75 and rownum() <= 100"。然而,由于Oracle是在排序之前指定rownum的值,因此,这样的查询"select * from Authors where rownum <= 25 order by Author_Last_Name"将得不到我们期望的结果。我们下面所讲的方法是针对SQL Server的,但这里的概念对适合Oracle开发人员也是适用的。

要创建一个返回指定条记录结果的存储过程,首先必须指定返回结果集的条记录数,可以用临时表,也可以用table变量(SQL Server 2000),两个在性能上没有太大的差别,但是,table变量是存储在内存中的,如果你的服务器内存不多的话,可以考虑用临时表,临时表使用硬盘存储结果,临时表需要手工释放对象,而table变量在存储过程结束后自动释放。下面就是我们要创建的存储过程:

create proc GetAuthors

@Author_Last_Name as varchar(100) = null,

@StartRow as int = null,

@StopRow as int = null

AS

---- 建立有标识符列的table变量

declare @t_table table

(

[rownum] [int] IDENTITY (1, 1) Primary key NOT NULL ,

[Author_Last_Name] [varchar] (40) ,

[Author_First_Name] [varchar] (20) ,

[phone] [char] (12) ,

[address] [varchar] (40) ,

[city] [varchar] (20) ,

[state] [char] (2) ,

[zip] [char] (5)

)

---- 在返回指定的@StopRow行数之后停止处理查询

Set RowCount @StopRow

---- 插入到table变量中

insert @t_table

(

[Author_Last_Name],[Author_First_Name],[phone],[address],[city],[state],[zip]

)

SELECT [Author_Last_Name],[Author_First_Name],[phone],[address],[city],[state],[zip]

FROM authors

WHERE Author_Last_Name like '%' + @Author_Last_Name + '%'

ORDER BY Author_Last_Name

---- 返回到正确的结果

SELECT * FROM @t_table WHERE rownum >= @StartRow

ORDER BY rownum

GO

参数@StartRow和@StopRow接收整数值,代表要返回的开始记录和结束记录,如果要在一个25条记录的页面中返回第4页,我们就可以设置@StartRow为76,@StopRow为100。我们在table变量@t_table中定义了一个叫rownum的整数类型的列,并指定为标识符列,这个列在我们这里介绍的分页技术中是很重要的,当我们插入数据时,这个列自动增加,它将在插入数据时起排序作用。SET ROWCOUNT语句对优化性能很关键,它告诉SQL Server进行限制要插入的数据,如果我们要76-100条记录之间的数据,那么就可以不必插入大于100条记录的数据。最后的SQL语句从@t_table的table变量选择rownum大于或者等于@StartRow的那些数据集,然后把它们返回到Web服务器,由Web服务器绑定到DataGrid对象。值得注意的是:如果要得到76到100条记录的数据,我们必须往table变量中插入100条记录的数据,这意味着:如果浏览者请求的页数越来越大,页面性能也会有所下降的。例如:要显示第100页的数据(从第2451条记录到第2500条记录),我们必须先向table变量或者临时表填充2500条记录,因此,性能依赖于你计算机的硬件和你要返回的记录数,有测试表明,在SQL Server 2000中使用这样的存储过程平均在200-250毫秒内返回第100页,而返回第一页只需要4毫秒。即使返回第500页的数据(从第12451到12500条记录)也可以在650到750毫秒内完成。应该说这种情况是很少见到的。 但为了减轻数据库和网络传输的压力,设计合理的查询结果页数是很见效的。

现在,我们写好了一个存储过程来做分页的工作,而不是用Web服务器来做这个事情,我们接下来要做的就是为DataGrid对象编写代码来使用我们的分页技巧。DataGrid的AllowPaging、AllowCustomPaging、PageStyle属性有助于避免我们编写自己的代码来跟踪记录浏览者目前在哪一个页面访问和都请求过哪些页面。我们应当设定AllowCustomPaging为True,否则,在你使用DataReader或者SQLDataReader绑定到DataGrid对象会遇到麻烦。在任何可能的情况下,应当尽量使用SQLDataReader而不要使用DataSet来装载DataGrid对象。据性能测试表明:在构建列表显示数据时,使用SQLDataReader比使用DataSet要快两倍以上。不要设定AllowPaging和PageStyle的值,这是因为,如果使用这两个属性,你必须在viewstate中维护DataGrid,但为了追求性能最佳化,我们必须设定DataGrid的EnableViewState属性为false,尽管这样我们自己必须编写一点代码来实现我们的分页,但是性能会有所提高的,因为在每次与Web服务器打交道时不必再在viewstate中存储内容了。

一旦我们关闭了DataGrid自己在viewstate中保存的能力,我们就必须自己编写代码来实现用户从一页导航到另一页。DataGrid如果自己不在viewstate中进行保存,那么它也不再跟踪记录“前一页”和“下一页”是哪些页面了。我们自己添加导航按钮来帮助浏览者进行导航。最简单的办法是在页面上增加两个按钮:“上一个”和“下一页”。要进入到下一页,我们在“下一页”按钮上增加click事件,通过我们的自定义分页存储过程请求相应的记录。例如:如果第一页由第1条到第25条记录组成,那么要导航到第二页,我们就向存储过程的@StartRow传递参数26,向@StopRow传递参数50即可,要返回到第一页,@StartRow和@StopRow分别为1和25。

下面是使用VB.NET编写的“下一页”事件的例子:

Private Sub ButtonNext_Click (ByVal sender As Object, _

ByVal e As System.EventArgs) Handles ButtonNext.Click

viewstate("StartRow") = viewstate("StartRow") + dgrid.PageSize

viewstate("StopRow") = viewstate("StartRow") + dgrid.PageSize

'运行存储过程,返回SQLDataReader

dgrid.DataSource = RunSprocReturnDR (textAu_lname.Text, _

textAu_fname.Text, viewstate("StartRow"),viewstate("StopRow"))

dgrid.DataBind()

End Sub

从上面的例子可以看出,我们在viewstate中保存的只是@StartRow和@StopRow的信息,这比在viewstate中保存整个DataGrid对象高效的多。“下一页”和“上一页”按钮提供的只是简单的导航,要实现更详细的导航信息,比如:共多少页、自定义页面记录数等,也是可以的,但要记住不要使用DataGrid内建的PagingStyle属性。根据测试表明,不保存DataGrid会提高性能到54%。

列表显示信息的性能对浏览者的访问是很重要的,设计不好的列表显示会大大降低应用程序的性能,不管它的后端数据库是多么快速。使用自定义分页技术,我们可以避免DataGrid默认分页机制带来的缺陷,如果要实现可搜索的列表显示,让你的用户感到你的应用程序快速和可扩展,还要编写更多的代码,相信各位会编写出更加优秀的程序的。

转载于:https://www.cnblogs.com/sunenic/archive/2004/07/27/27803.html

利用自定义分页技术提高数据库性能相关推荐

  1. 利用相控阵馈源技术提高射电望远镜性能

    电子科技大学 格拉斯哥学院2017级 邵子扬 前言 作为天文学的一个新兴的分支,直到上世纪三十年代Jansky发现来自银河的无线电波,射电天文学才真正出现[1],而真正开始发展又是十年后的事情了.所以 ...

  2. 利用过采样技术提高ADC测量微弱信号时的分辨率

    1. 引言 随着科学技术的发展,人们对宏观和微观世界逐步了解,越来越多领域(物理学.化学.天文学.军事雷达.地震学.生物医学等)的微弱信号需要被检测,例如:弱磁.弱光.微震动.小位移.心电.脑电等[1 ...

  3. 利用 squid 反向代理提高网站性能

    本文在介绍 squid 反向代理的工作原理的基础上,指出反向代理技术在提高网站访问速度,增强网站可用性.安全性方面有很好的用途.作者在具体的实验环境下,利用 DNS 轮询和 Squid 反向代理技术, ...

  4. 如何利用区块链技术提高人力资源管理效率?

    过去,在经济发展中,我们不断强调的是"科技是第一生产力."随着互联网的迅速普及和发展,让信息快速传播且成本趋于零.伴随着区块链技术的应用和发展,区块链企业如雨后春笋般涌现,且其发展 ...

  5. 数据库性能优化步骤_五个简单步骤即可提高数据库性能

    数据库性能优化步骤 2015年1月30日:根据读者的反馈意见,第4节"您是否有足够的数据库连接?" 已修改. 数据库访问是大多数应用程序的核心功能. 根据我们的经验,对于我们看到的 ...

  6. 《机器学习实战》学习笔记(七):利用AdaBoost 元算法提高分类性能

    欢迎关注WX公众号:[程序员管小亮] [机器学习]<机器学习实战>读书笔记及代码 总目录 https://blog.csdn.net/TeFuirnever/article/details ...

  7. 利用AdaBoost元算法提高分类性能

    本篇博文涵盖如下内容: 组合相似的分类器来提高分类性能 应用AdaBoost算法 处理非均衡分类问题 元算法(meta-algorithm): 对其他算法进行组合的一种方式. 最为流行的元算法: Ad ...

  8. 机器学习实战 -- 利用AdaBoost 元算法提高分类性能

    组合相似的分类器来提高分类性能 应用AdaBoost算法 处理非均衡分类问题 元算法是对其他算法进行组合的一种方式. 基于数据集多重抽样的分类器 我们可以将不同的分类器组合起来,而这种组合结果被称为集 ...

  9. 如何优化数据库?如何提高数据库性能?

    1.给数据库建立索引,合理的索引可以显著地提高数据库整个性能. 2.在适当的情况下,尽可能使用 储存过程 而不是SQL查询 ,因为前者已经预编译了,运行速度更快! 3.优化查询语句,通过高性能的查询语 ...

最新文章

  1. 程序化广告(4):考核指标
  2. NAR:查询未培养病毒基因组的综合生态和进化框架IMG/VR v3
  3. OkHttp3 websocket
  4. CSS Sprites图片合并
  5. Python3 中hasattr()、getattr()、setattr()、delattr()函数及示例代码数
  6. 破五唯后,高校从“唯论文”变成了“唯纵向”?​
  7. jenkins 手动执行_Jenkins Git client插件命令执行漏洞(CVE201910392)
  8. ReadOnly与Enabled
  9. 全屏窗口指令_在iOS 14系统中,快捷指令原来有多达11种运行方式(上篇)
  10. 硬盘安装Linux系统的最简单方法
  11. C#实现目录跳转(TreeView和SplitContainer)
  12. matlab中多项式拟合polyfit()和插值函数polyval()的基础使用方法和历程
  13. CentOS7定制Gnome3外观
  14. 计算机文档我的文档丢失,我的文档不见了
  15. 树莓派运行yolo fastest启用bf16加速
  16. Python之父退休,龟叔与Python的渊源
  17. 论文参考文献格式自动生成
  18. 复旦961-软件工程笔记
  19. Python 程序员需要知道的 30 个技巧(转载)
  20. Outlook 2013 英文版 设置收信规则

热门文章

  1. Java微服务(一)【idea安装2020版本】
  2. 互联网造富亲历者讲述:屌丝富了以后
  3. Oracle EM 配置常用命令
  4. IT行业分析之企业信息化技术
  5. H5开发 连接蓝牙打印机 打印标签(斑马ZR628)
  6. android data binding jetpack III 绑定一个方法
  7. Asp.net几大内置对象
  8. 随着firefox的迭代更新:FireBug不能用了?使用火狐Try Xpath插件替代Firebug和Firepath...
  9. 【原】动态申请二维数组并释放的三种方法
  10. 01Spring的helloworld程序