当前位置:  数据库>sqlserver

TOP N与Row_Number()分页因Order by排序规则不同引发的bug

    来源: 互联网  发布时间:2014-08-29

    本文导语:  使用SQL Server 2005的Row_Number()函数分页,使分页变得简单和高效。 在一个系统核心表(百万级数据量)分页时为提高效率采用了Row_Number()函数和TOP N相结合的分页方法。 具体实现:取第1页数据时语句为“select top pagesize column1,colum...

使用SQL Server 2005的Row_Number()函数分页,使分页变得简单和高效。

在一个系统核心表(百万级数据量)分页时为提高效率采用了Row_Number()函数和TOP N相结合的分页方法。

具体实现:取第1页数据时语句为“select top pagesize column1,column2 from tablename order by columnname”,取第1页以后的数据时语句为“select * from (select column1,column2,ROW_NUMBER() over(order by columnname) as rownum from tablename) T where T.rownum between startnum and endnum”。看似是没什么问题,都是根据columnname排序的,绝大部情况也确实没问题,但遇到极少数特别情况,问题就暴露出来了。(第一页用TOP N取数据是不是真的比用Row_Number()快,并没有找到理论证明,而且我测试的结果是用Row_Number()快些,希望这方面能得到朋友的指导。)

问题:显示给用户的记录是根据时间倒序的,陆陆续续收到用户的反映“第一页和第二页出现相同的记录”、“有的记录没有出现在任何页”,但这种现象是极其个别的,而且出现的时间都很短暂很难重现。

后来接到一用户反映,马上查看该用户数据,惊奇的发现排序字段columnname有相同的值,而且用TOP N取第1页数据和用Row_Number()函数取第1页数据时取出来的数据不同,这样就可以解释为什么有的记录出现在两个页面有的记录没有出现了。

至于出现时间很短暂,因为排序字段columnname会被频繁的更新。

测试两种取第1页数据的方法:
 

代码示例:

--1.创建测试表
CREATE TABLE TestOrder(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [refTime] [datetime] NOT NULL,
 CONSTRAINT [PK_TestOrder] PRIMARY KEY CLUSTERED
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF
, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]


--2.插入测试数据
declare @i int
set @i = 0
while @i < 50
begin
    insert into TestOrder(refTime) values(getdate())
    set @i = @i + 1
end

--通过top取前5条数据
select top 5 * from TestOrder order by refTime

--通过row_number()取前5条数据
select * from (
select *,ROW_NUMBER() over(order by refTime) as rownum from TestOrder
) T where T.rownum between 1 and 5

--5.删除测试表
drop table TestOrder

通过TOP N取出来的前5条数据:
 

id   refTime
6 2010-06-21 23:52:59.123
5 2010-06-21 23:52:59.123
4 2010-06-21 23:52:59.123
3 2010-06-21 23:52:59.123
2 2010-06-21 23:52:59.123

通过Row_Number()取出来的前5条数据:
 

id   refTime  rownum
1 2010-06-21 23:52:59.123 1
2 2010-06-21 23:52:59.123 2
3 2010-06-21 23:52:59.123 3
4 2010-06-21 23:52:59.123 4
5 2010-06-21 23:52:59.123 5

可见,但RefTime相同时,两者取出来的第1页数据是不同的,Row_Number() over(order by)和where后的order by产生的排序规则并不完全相同,不能简单的将二者等同起来,结合在一起使用可能会造成意想不到的bug。

希望以上的分析对遇到相同问题的朋友,有所帮助或启发。


    
 
 
 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • C++ Stacks(堆栈) 成员 top():返回栈顶元素
  • top查看CPU 发现top本身占用率奇高
  • java命名空间java.awt类insets的类成员方法: top定义及介绍
  • top与ps命令输出结果差异以及top结果的重定向
  • mysql iis7站长之家
  • top -d 1 | grep gedit为什么不能1秒钟刷新一次?top -d 1 就可以1秒钟刷新一次
  • java命名空间javax.swing接口swingconstants的类成员方法: top定义及介绍
  • jQuery获取margin-top与padding-top值
  • java命名空间javax.swing.border类emptyborder的类成员方法: top定义及介绍
  • shell 程序中top 命令屏幕限制
  • java命名空间javax.swing类jsplitpane的类成员方法: top定义及介绍
  • 请教Solaris 10 安装TOP工具不能使用的问题
  • java命名空间javax.swing.border类titledborder的类成员方法: top定义及介绍
  • hp_ux下如何使用java获取top信息
  • java命名空间javax.print.attribute.standard类mediatray的类成员方法: top定义及介绍
  • 我是个小菜鸟。想问问top命令如何保存
  • java命名空间javax.lang.model.element枚举nestingkind的类成员方法: top_level定义及介绍
  • 求solaris下的类似linux的top命令,谢谢!
  • java命名空间javax.swing.border类titledborder的类成员方法: above_top定义及介绍
  • top:unknown terminal type 问题
  • java命名空间javax.swing.border类titledborder的类成员方法: below_top定义及介绍
  • 页面中的Top是如何实现的?


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3