首 页 | 新 闻 | 技术中心 | 第二书店 | 《程序员》 | 《开发高手》 | 社 区 | 黄 页 | 人 才
移 动专 题SUNIBM微 软微 创精 华Donews人 邮
我的技术中心 
我的分类 我的文档
全部文章 发表文章
专栏管理 使用说明



 RSS 订阅 
最新文档列表
Windows/.NET
.NET  (rss)    
Visual C++  (rss)    
Delphi  (rss)    
Visual Basic  (rss)    
ASP  (rss)    
JavaScript  (rss)    
Java/Linux
Java  (rss)    
Perl  (rss)    
综合
其他开发语言  (rss)    
文件格式  (rss)    
企业开发
游戏开发  (rss)    
网站制作技术  (rss)    
数据库
数据库开发  (rss)    
软件工程
其他  (rss)    

积极原创作者 
btbtd (83)
coofucoo (107)
longrujun (64)
cyz1980 (101)
ssll2826 (10)
EmilMatthew (73)
goodboy1881 (15)
superlmj (12)
feng19821209 (9)
yjz0065 (115)
CSDN - 文档中心 - .NET 阅读:7542   评论: 8    参与评论
标题   DataGrid连接Access的快速分页法(1)——需求与现状     选择自 upto 的 Blog
关键字   DataGrid,Access,分页
出处  

DataGrid连接Access的快速分页法(1)——需求与现状

一、需求分析

     DataGrid是一个功能强大的ASP.NET Web服务器端控件,它除了能够按各种方式格式化显示数据,还可以对数据进行动态的排序、编辑和分页。大大减轻了广大Web程序员的工作量。实现DataGrid的分页功能一直是很多入门者感到棘手的问题,特别是自定义分页功能,实现的方法多种多样,非常灵活。
 
     目前大家公认性能最好的应该数SQL Sever结合存储过程的解决方案。因为在SQL Server的存储过程里面可以使用游标(Cursor)来遍历数据库表中所有的行,结合一个计数器变量就可以快速定位到数据库表中的某一行了。但是在采用Access数据库的ASP.NET应用程序中,一直没有一种较好的解决方案。
 
     我们知道,在ASP中可以使用ADO的游标来快速定位当前页面的数据在数据库表中的位置。可是ADO.NET中没有游标这个东西,所以传统的DataGrid分页方法都是用诸如“SELECT * FROM Item”的SQL语句从数据库表中取出所有的记录,然后DataGrid的自动分页功能会帮你显示相应分页的数据。

二、目前的解决方案

     很多人已经意识到了上面描述的问题,并提出了解决方法,即采用自定义分页,每次从数据库表中取出要显示的数据。那么,怎样取呢?答案就我知道的大概有5种以上吧。使用不同的算法,将会得到不同的效率。经过我粗略的测试,最慢的算法耗费的时间大概是最快的3倍!而且这个数字会随着记录总数的增加而增加。
 
     为了方便接下来的讨论,在展示 SQL 语句之前,首先让我们做如下约定:
 
PageIndex

ItemId

ProductId

Price

0

001

0011

$12

002

0011

$13

003

0011

$12

1

004

0012

$13

005

0012

$11

006

0012

$14

2

007

0013

$14

008

0013

$12

009

0014

$13

3

010

0011

$13

011

0012

$15

012

0014

$16

4

013

0013

$12

014

0013

$13

 
变量
用途
@PageSize
每页显示的记录总数
@PageCount
分页总数
@RecordCount
数据表的记录总数
@PageIndex
当前页的索引
@FirstIndex
第一页的索引
@MiddleIndex
中间页的索引
@LastIndex
最后一页的索引
@TableName
数据库表名称
@PrimaryKey
主键字段名称
@QueryFields
要查询的字段集
@Condition
筛选条件
 
定义:
@PageCount  = (int)Math.Ceiling((double)@RecordCount / @PageSize)
@FirstIndex = 0
@LastIndex  = @PageCount - 1
@MiddleIndex     = (int)Math.Ceiling((double)@PageCount / 2) – 1
 
预设:
@PageSize = 2
@RecordCount = 9
@PageCount = 4
 
     现在先让我们来看看速度最慢的 SQL 语句:
 
SELECT TOP @PageSize * FROM @TableName AS a
WHERE @PrimaryKey NOT IN (
     SELECT TOP @PageSize*@PageIndex @PrimaryKey FROM @TableName AS b
     ORDER BY @PrimaryKey
)
ORDER BY @PrimaryKey
 
     这条语句慢就慢在 NOT IN 这里,主 SELECT 语句遍历的每个 @PrimaryKey 的值都要跟子 SELECT 语句的结果集中的每一个 @PrimaryKey 的值进行比较,这样时间复杂度非常大。其实我们平时编写 SQL 语句的时候应该尽量避免用 NOT IN 语句,因为它往往会提高整个 SQL 语句的时间复杂度。
 
     还有一种是用两个 TOP 的 SQL 语句,如下所示:
 
SELECT * FROM (
     SELECT TOP @PageSize * FROM (
          SELECT TOP @PageSize*(@PageIndex+1) * FROM @TableName
          ORDER BY @PrimaryKey
     ) TableA
     ORDER BY @PrimaryKey DESC
) TableB
ORDER BY @PrimaryKey
 
     这条 SQL 语句空间复杂度比较大。如果要显示的分页面刚好是最后一页,那么它的效率比直接SELECT 出所有的记录还要低。
 
     下一篇将详细介绍一种最快的算法,并根据不同情况,采用不同的变形来有效的提高查询效率。
 
 
作者:黎波

相关文章
对该文的评论
sendidmax ( 2004-07-05)
如果是order Pkey1 desc, Pkey2 asc, Pkey3 desc 呢?
upto ( 2004-03-24)
to ipconfiger

下面引用MSDN一篇文章的内容:
----------------------------------
SqlDataAdapter通过startRecord和maxRecords把所有结果都拷贝到新生成的DataSet中,并丢弃不需要的数据。这意味着许多不必要的数据将潜在的通过网络进入数据访问客户--这是这种方法的主要缺陷。 

比如,如果有1000个记录,而需要的是第900到950个记录,那么前面的899个记录将仍然穿越网络然后被丢弃。对于小数量的记录,这种开销可能是比较小的,但如果针对大量数据的分页,则这种开销就会非常巨大。 
----------------------------------

原文:
.NET 数据访问架构指南
http://www.microsoft.com/china/msdn/adonet.asp
ipconfiger ( 2004-03-23)
有这么麻烦么?在dataadapter的fill方法里有一个重载的方法可以填充从某项记录后多少条记录,这个方法可以很方便的分页了,而且效率也不差,怎么好象根本没几个人知道的样子?
jiangchuandong ( 2004-03-08)
呵呵,看过了,不错
upto ( 2004-03-08)
to zsucc
谢谢您的指正!

说实话,小弟现在大三,水平很有限。上个学期开了数据库的课,对数据库很感兴趣。目前正在努力学习SQL Server中,对SQL Server还有很多不了解的地方。写本文是想把我的想法告诉大家,当然希望该想法对大家是有用的:)其实写本文的过程中我挺担心自己会有说得不当的地方,毕竟自知之明:(但是小弟急于把好东西尽快与大家分享,所以还是鼓起勇气,把文章发表出来了。

希望大家帮忙指出文中说得不当的地方,特别是数据库方面。一来怕误导读者,而来可以让我增长见识:)

再次感谢 zsucc ,希望您继续阅读其他篇幅!