随笔-35  评论-80  文章-2  trackbacks-0

Sql Server2005中获取表中某一列的最大值使用MAX和TOP-ORDER BY执行效率比较

今天在CSDN看到这样的一个帖子,于是用SqlServer2005查询分析器测试了一下。

测试之前,我个人认为是MAX,测试之后发现是TOP-Order BY

要求:获取表中某一数值列的最大值

语句:

        1)select top 1 Number from pager order by Number desc
   2)select Max(Number) from pager

数据表:

        1)Pager表,3列,20000行数据,其中ID是主键列、自增标识列,无其他索引

        2)Pager2表,3列,20000行数据,其中ID是自增标识列,该表无主键列,无其他索引

执行:

       1)使用Pager表 分别运行两条T-Sql语句4次

       2)使用Pager2 表 分别运行两条T-Sql语句4次

 下面开始:

     1-1  Pager表: select top 1 Number from pager order by Number  desc。下图中是使用主键列ID排序后的执行计划和客户端统计信息

       执行计划

 

     客户端统计信息

 

  1-2  Pager表: select Max(Number) from pager

       执行计划

 

       客户端统计信息

 

   2-1  Pager2表: select top 1 Number from pager2 order by Number desc

         执行计划

 

        客户端统计信息 

 

  2-2  Pager2表: select Max(Number) from pager2

        执行计划

 

        客户端统计信息

 

 

 

      从这些数据结果来看:

       1)使用Pager表,大数据量时Top-Order by语句的执行效率优势相当明显

       2)使用Pager2表时, Top-Order by语句的执行效率依然有明显的优势

 

       不当之处,欢迎指正! 

       -------------谢谢指正!

       补充1): 在使用Pager表时,由于排序列使用了ID(主键),所以从数据上看效率很高;但实际排序列应该是Number,此时效率要降低不少。

                        其实,在做这个测试的时候,我是循环往表中Number列插入1到20000,所以在此表中ID列的排序也是Number列的正确排序结果,而效率更高。

                        而实际应用中并不一定这么巧合。

4
3
(请您对文章做出评价)
« 上一篇:页面操作完成时,显示提示信息并倒计N秒后跳转(草)
» 下一篇:Enterprise Library 4.0 Data Access Application Block 配置使用介绍
posted on 2009-07-14 11:39 CC.FENG 阅读(2196) 评论(17)  编辑 收藏 网摘 所属分类: Sql Server

评论:
#1楼 2009-07-14 11:52 | 阿水      
我测试的结果好像差不多。我的记录比较少,只有两万多。
  回复  引用  查看    
#2楼 2009-07-14 11:53 | 金色海洋(jyk)      
1)select top 1 Number from pager order by ID desc
2)select Max(Number) from pager

=========

1、这两个SQL语句是等效的吗?

应该改成这样吧?

1)select top 1 ID from pager order by ID desc
2)select Max(ID) from pager

或者

1)select top 1 Number from pager order by Number desc
2)select Max(Number) from pager




2、

select top 1 Number from pager order by ID desc
这个SQL运行速度快,那是因为 ID 是主键,建立了聚集索引,你可以把ID的主键去掉(就是去掉ID的聚集索引),然后你看对比一下效率。


另外 SQL 好像对于 自增标识列 也做了一些优化。


3、非常支持lz做测试的这种方法,以前我也做过不少测试(类似的功能),但是我觉得这两个SQL语句并不是等效的,所以测试结果就。。。。。。。



  回复  引用  查看    
#3楼 2009-07-14 11:53 | 斯克迪亚      
楼主,你那个测试用的软件是什么呀?能说一下吗
  回复  引用  查看    
#4楼 2009-07-14 11:59 | 金色海洋(jyk)      
取 Number 列的最大值,为什么要按照ID字段排序呢?

Number 列和ID列的值是完全一致的吗?如果是的话,为什么要设置成两个字段呢?呵呵。

如果不完全一致,那么就不能按照ID字段排序,呵呵。


===

怎么两个 2楼,看来并发没有处理好呀。

  回复  引用  查看    
#5楼 2009-07-14 12:10 | egmkang      
@斯克迪亚
management里面自带的

  回复  引用  查看    
#6楼[楼主] 2009-07-14 12:25 | CC.FENG      
引用金色海洋(jyk):
1)select top 1 Number from pager order by ID desc
2)select Max(Number) from pager

=========

1、这两个SQL语句是等效的吗?

应该改成这样吧?

1)select top 1 ID from pager order by ID desc
2)select Max(ID) from pager

或者

1)select top 1 Number from pager order by Number desc
2)select Max(Number) from pager...


对 排序列应该是Number,谢谢指正

  回复  引用  查看    
#7楼 2009-07-14 12:32 | 不死鸟之魂      
博主应该用Max(ID)来比较,而不是Max(Number),因为Number没有索引,速度理论上来说是比不上ID的(之所以说理论,是因为我没试过)。
当然,因为实际需要查询的是Number的值,所以第二种方法实际还需要使用一条select语句才行。

  回复  引用  查看    
#8楼[楼主] 2009-07-14 13:01 | CC.FENG      
引用斯克迪亚:楼主,你那个测试用的软件是什么呀?能说一下吗

SqlServer2005 ManagementStudio中新建查询窗口,在工具栏会有两个按钮:包括执行计划、包括客户端统计信息

  回复  引用  查看    
#9楼 2009-07-14 13:33 | 鸽子飞扬      
原来可以建2个2楼的,hoho

  回复  引用  查看    
#10楼 2009-07-14 14:15 | charlif[未注册用户]
个人觉得还是Max()的效率高。
楼主的测试有误,虽经别人指正,但你所贴图仍然是order by id desc
所以从贴图来说无任何参考价值。

这个还是要看所测试的列是否是聚集索引列了
如果是聚集索引列,那么两者在效率上来说应该是相同的
如果是非聚集索引列,Max()的效率要高一些

Max()是流聚合--》聚集索引扫描
top1 是排序--》聚集索引扫描

可以看到排序的开销远远要大于流聚合的开销。

PS:如果TOP 1的效率高,微软还有必要费那么大劲搞个Max()出来吗?

  回复  引用    
#11楼[楼主] 2009-07-14 14:59 | CC.FENG      
引用charlif:
个人觉得还是Max()的效率高。
楼主的测试有误,虽经别人指正,但你所贴图仍然是order by id desc
所以从贴图来说无任何参考价值。

这个还是要看所测试的列是否是聚集索引列了
如果是聚集索引列,那么两者在效率上来说应该是相同的
如果是非聚集索引列,Max()的效率要高一些

Max()是流聚合--》聚集索引扫描
top1 是排序--》聚集索引扫描

可以看到排序的开销远远要大于流聚合的开销。

PS:如果TOP 1的效率高,微软还有必要费那么大劲搞个Max()出来吗?

第一种情况确实是使用了索引列排序,这或许也能成为将来某个应用中的解决方案
第二种情况则不是,图还是有参考价值的

第二种情况经过多次测试,依然是top-order by语句的总执行时间小于max语句


  回复  引用  查看    
#12楼 2009-07-14 15:08 | 金色海洋(jyk)      
Max() 是ANSI SQL 92 标准里面定义的,就是说各大数据库厂商必须实现的。

而top 是微软弄出来的,Orcale、MySQL里面就没有top。

所以说,有没有max,和效率没有关系的,呵呵。


  回复  引用  查看    
#13楼 2009-07-14 16:35 | charlif[未注册用户]
楼主把测试的数据量加大。2W条太少了
我在SQL2008下面,搞了500W的数据

对聚集索引列进行比较,5次取平均值
Max()总运行时间6.2,TOP总运行时间5.4,二者基本相同,可见在聚集索引情况下无差别。

对非聚集索引列进行比较,5次取平均值
Max()总运行时间942.8,TOP总运行时间1621.4,可以看到二者差距较大,Max()的效率明显比TOP的效率要高。

  回复  引用    
#14楼 2009-07-14 16:45 | elevenbus[未注册用户]
两者的用途都不一样啊
如果要取两个以上的聚合值,就不能使用top 了

  回复  引用    
#15楼 2009-07-14 18:01 | 斯克迪亚      
引用CC.FENG:
引用斯克迪亚:楼主,你那个测试用的软件是什么呀?能说一下吗

SqlServer2005 ManagementStudio中新建查询窗口,在工具栏会有两个按钮:包括执行计划、包括客户端统计信息

非常感谢:)
我数据库方面经验是在太少了呵。

  回复  引用  查看    
#16楼 2009-07-14 23:07 | 路过2009[未注册用户]
这种稀里糊涂的东西,自己还没搞清楚竟然还能得到4个推荐。


  回复  引用    
#17楼 2009-07-15 08:21 | Ferry[未注册用户]
引用路过2009:
这种稀里糊涂的东西,自己还没搞清楚竟然还能得到4个推荐。


呵呵,我并没有说这个结论就一定是“百试皆爽",而且因为索引、数据量等客观原因的存在,结论可能存在片面性,所以拿出来,大家讨论。因为在csdn大家的意见也不一致,我想都没经过详细测试吧

  回复  引用