漂泊雪狼的博客

思考,讨论,分享C#,JavaScript,.NET,Oracle,SQL Server……技术
posts - 47, comments - 259, trackbacks - 9, articles - 10
      在《用ObjectDataSource实现自定义分页的心得总结》中,在SQL Server中使用双Top查询,后来用“事件探查器”进行性能对比,发现在SQL Server 2005中使用RowNumber函数的方法更有效;在SQL Server 2000中无法使用RowNumber函数,但是数据量较大时,双Top查询速度很慢,排序的字段若没有建立索引后果更加糟糕,其实在SQL Server 2000中,可以巧妙的使用SET ROWCOUNT和表变量来实现自定义分页,如下是一个参考示例:
      
利用表变量分页

在上面的代码中,如果EmployeeID是唯一的(一般在数据库设计的时候推荐在表中加一个自增列的字段来取代它),可以不用表变量切性能可进一步得到优化,具体代码如下:
优化的分页程序

在SQL Server 2005和Oracle 9i后的版本中可以分别使用ROWNUMBER和ROWNUM来进行分页,并能获得较好的性能,以SQL Server 2005为例,一般的做法如下:
1SELECT 
2FROM
3   (SELECT  
4         ROW_NUMBER() OVER(ORDER BY ColumnName) as RowNum
5    FROM Employees e
6   ) as DerivedTableName
7WHERE RowNum BETWEEN @startRowIndex AND (@startRowIndex + @maximumRows- 1
8
9
但是有一个小问题,如果最里面的一层查询有重复值,上面的排序将会出现问题,最好将代码优化成如下形式:
 1SELECT
 2(
 3    SELECT ,
 4    ROW_NUMBER() OVER(ORDER BY ColumnName) as RowNum
 5    FROM
 6       (SELECT DISTINCT          
 7        FROM Employees e
 8        INNER JOIN f
 9        ON e.id = f.id
10       ) AS DerivedTableName
11AS Temp
12WHERE RowNum BETWEEN @startRowIndex AND (@startRowIndex + @maximumRows- 1
之所以要这么做是为了是DISTINCT发挥作用,因为在SQL Server2005中DISTINCT和ROW_NUMBER()一起使用,DISTINCT将不能过滤掉重复的记录,在Oracle中DISTINCT和ROWNUM也会同样出现这样的问题,这些都是本人在实际项目中遇到的问题并总结出来的,或许你有更好的方法,可以在我的博客中留言,谢谢!

参考文章:http://aspnet.4guysfromrolla.com/articles/031506-1.aspx

Feedback

#1楼   回复  引用  查看    

2007-06-12 16:26 by henry      
其实直接用DataReader分即省事又方便,效率和ROWNUMBER或ROWNUM差不多.

#2楼[楼主]   回复  引用  查看    

2007-06-12 16:29 by 漂泊雪狼      
to henry :
用DataReader 而不用Rownumber和ROWNUM,你如何控制读取的起至位置?写在业务逻辑中吗?

#3楼   回复  引用  查看    

2007-06-12 16:36 by henry      
@漂泊雪狼
既然有开始行和结束行难道Read不成(这样的分页是和数据库无关性的),
其实ROWNUMBER或ROWNUM做的工作和游标差不多,只是MSSQL和Oracle定义这样的东西在编写SQL方便一点,难首你以为从100开台就不会把0-99的读出来?这个东西分页的效率还会受读取字段数影响。

#4楼[楼主]   回复  引用  查看    

2007-06-12 16:50 by 漂泊雪狼      
用ROWNUMBER或ROWNUM绝对比游标的效率要高,用DataReader可以实现你所的分页,但那是在逻辑层控制DataReader的读取操作,分页的负担给了web服务器,用存储过程分页可以减轻web服务器负担,让数据库服务器来做这些,且根据不同的数据库提供不同的分页实现方式,可以提高程序的性能。

#5楼   回复  引用  查看    

2007-06-12 17:10 by henry      
@漂泊雪狼
用ROWNUMBER或ROWNUM绝对比游标的效率要高?你真的实践过?
我做一个实践有一个一百W记录的表20个字段,用游标遍历主索引分页然后再根据当前页的主索引重新获取记录,
越往后走游标这种分页比ROWNUMBER或ROWNUM分页的效率按倍数增长。
还有一个问题,你认为数据库集群方便还是webapp集群方便?

#6楼   回复  引用  查看    

2007-06-12 17:26 by neuhawk      
我们是用存储过程~~~~~~~~~

#7楼   回复  引用  查看    

2007-06-13 12:02 by Cat Chen      
好像这种情况下应该用SqlDataSource而非ObjectDataSource啊。ObjectDataSource是用于已经经过业务逻辑层封装的对象的,也就是说在业务逻辑层封装出分页接口就行了,我并不需要管背后的数据访问层用关系型数据库还是XML。然而你这篇文章的讨论重点是SQL,所以应该用SqlDataSource才对啊。

#8楼   回复  引用    

2007-06-13 14:16 by 4x4y[未注册用户]
其实直接用DataReader分即省事又方便
搞笑太搞笑了,DataReader里面的数据哪里来的,是从数据库读取填充进来的,这里的分页就是就是只返回特定的数据库记录条数。不过这篇文章标题严重误导,楼主的意思其实就是从数据库中按需读取所需记录,和上面的ObjectDataSource压根没有关系,至于读取出来了你用DataReader用什么都成。

#9楼[楼主]   回复  引用  查看    

2007-06-13 15:41 by 漂泊雪狼      
这篇文章是《用ObjectDataSource实现自定义分页的心得总结》的后继篇,
上篇中我提到用ObjectDataSource分页的好处,但是在项目应用中我发现上篇中的分页存储过程效率可以继续提高和优化,于是写了这篇!



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

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

0 780589




相关文章:

相关链接:
Search Engine Optimization