第1 和第2 种的写法,基本上是一样的,区别不大,性能应该基本上一样。而第3种,多关联了一次Tab_Info,相对于1、2,性能可能稍微会差一点。你最好实际运行一下这3个语句:--用来检测io、cpu 的开销
set statistics io on
set statistics time on
语句1语句2语句3

解决方案 »

  1.   


    这是一个办法,
    开这个主要是向得到一些原理性能的分析大概是两方面的问题
    1、先定位有限的记录再inner join 查询还是先inner join再定位有限的记录
       最后一个存储过程和前两个的比较
    2、类似select xxx from (select ....)语句的执行过程问题,
       是否是先执行括号内的select然后把结果存在内存,
       之后再执行外层的select
      

  2.   

    占用资源的话,开Profiler就有很多CPU、io、duration等实时信息
      

  3.   


    这是一个办法,
    开这个主要是向得到一些原理性能的分析大概是两方面的问题
    1、先定位有限的记录再inner join 查询还是先inner join再定位有限的记录
       最后一个存储过程和前两个的比较
    2、类似select xxx from (select ....)语句的执行过程问题,
       是否是先执行括号内的select然后把结果存在内存,
       之后再执行外层的select这个顺序不能保证,优化器可能会改写你的查询
      

  4.   


    1、第2种比第1种写法多用了一次select,是否在执行过程中会占用更多的内存,
     类似select xxx from (select ....)语句的执行过程问题,
       是否是先执行括号内的select然后把结果存在内存,
       之后再执行外层的select 2、第3种先定位有限的几条记录,然后再和其他表关联更多的字段
       第1、2种先把所有的字段 关联在一起,然后在从这些记录中选取有限的几条记录,
       第1、2种是否比第3种占用更多的内存
       特别是要关联某个表的大量字段的时候
      

  5.   


    这是一个办法,
    开这个主要是向得到一些原理性能的分析大概是两方面的问题
    1、先定位有限的记录再inner join 查询还是先inner join再定位有限的记录
       最后一个存储过程和前两个的比较
    2、类似select xxx from (select ....)语句的执行过程问题,
       是否是先执行括号内的select然后把结果存在内存,
       之后再执行外层的select1.一般来说肯定是先定位有限的记录,然后再inner join,这样更好,但是你会发现,只要你的语句不是太复杂,那么经过sql server优化器的优化,先定位有限的记录再inner join 查询,还是先inner join再定位有限的记录,这2种语句会产生相同的执行计划,也就是说性能是一样的。2.类似select xxx from (select ....)语句的执行过程,一般就是先执行里面的,然后对产生的结果集,再执行外面的一层。
    但是如果你的语句不是特别复杂,不是嵌套好多次,不是一堆的where条,不是一堆的join,那么经过sql server的优化,比如下面的2个语句:select * from (select * from tb where xxx = 123);select * from (select * from tb) where xxx = 123会产生一样的执行计划,所以性能也是一样的。
      

  6.   

    但是,如果你的语句比较复杂,那么sql server的优化器,对这2种语句,就很有可能会产生不同的执行计划,那么就会导致性能的差异了。所以,你说的挺对的,最好是采用,现过滤数据,再join;先过滤数据,再在外面加一层select from,这种语句看上去更加简单,其实对于sql server也是一样的,这种语句也更容易产生好的执行计划,提高查询的性能。
      

  7.   


    先过滤数据,再join除了性能上的提高外,是否在占用内存上是不是也会少些?
    因为先join会得到大量记录集,然后从记录集中筛选有限的几条,
    而先过滤就可以让记录集很小,然后join
      

  8.   


    先过滤数据,再join除了性能上的提高外,是否在占用内存上是不是也会少些?
    因为先join会得到大量记录集,然后从记录集中筛选有限的几条,
    而先过滤就可以让记录集很小,然后join理论上是会占用少。如果数据集太大,join的算法也会不同
      

  9.   

    根据数据量、索引情况、是否有预排序等情况,join的不同算法有不同的效率
      

  10.   


    1、第2种比第1种写法多用了一次select,是否在执行过程中会占用更多的内存,
     类似select xxx from (select ....)语句的执行过程问题,
       是否是先执行括号内的select然后把结果存在内存,
       之后再执行外层的select 2、第3种先定位有限的几条记录,然后再和其他表关联更多的字段
       第1、2种先把所有的字段 关联在一起,然后在从这些记录中选取有限的几条记录,
       第1、2种是否比第3种占用更多的内存
       特别是要关联某个表的大量字段的时候
    1、不会占用更多内存,其实第1种和第2种的写法基本上没什么区别,只是1是这样 select from a inner join b,而2 是 select from (a inner join b),两个语句,应该会有一样的执行计划的。2、第3种是先top 2,然后把结果集在和另外的2个表关联,这种思路是对的,先过滤数据,然后再关联,只是,比1和2,多关联了一次表,性能不一定好,还是得执行一下来比较。另外,你的3个语句,都可以进行简化,没必要用top 2,我以第1个语句作为例子:
    select * 
    from 
    (
    select sortval,id,pushtime,name,details 
    from 
    (
    select row_number()over(order by pushtime desc)as sortval,id,pushtime,name 
    from Tab_Push 
    inner join Tab_Info 
    on tarmac=@mac and Tab_Push.id = Tab_Info.id and Tab_Info.isenable=1
    ) A
    inner join Tab_infoEx on A.id = Tab_infoEx.id
    )B 
    where sortval > @sortval and sortval <= 2   --取前2条
      

  11.   


    先过滤数据,再join除了性能上的提高外,是否在占用内存上是不是也会少些?
    因为先join会得到大量记录集,然后从记录集中筛选有限的几条,
    而先过滤就可以让记录集很小,然后join对的,先有小的结果集,然后再次join,效率会更高,不仅是cpu,io也会小很多。
      

  12.   

    还可以进一步简化:select * 
    from 
    (
    select row_number()over(order by pushtime desc)as sortval,id,
           pushtime,name,details 
    from Tab_Push 
    inner join Tab_Info 
    on tarmac=@mac and Tab_Push.id = Tab_Info.id and Tab_Info.isenable=1
        inner join Tab_infoEx on Tab_Push.id = Tab_infoEx.id
    )B 
    where sortval > @sortval and sortval <= 2   --取前2条
    另外,直接把3个表,进行关联,这样和先关联前2个,再关联第3个相比,其实语句还简单一点,因为sql server内部,处理这种 join时,其实就是两个两个表的关联的,再把关联的结果集,和第3个表关联。
      

  13.   


    1、第2种比第1种写法多用了一次select,是否在执行过程中会占用更多的内存,
     类似select xxx from (select ....)语句的执行过程问题,
       是否是先执行括号内的select然后把结果存在内存,
       之后再执行外层的select 2、第3种先定位有限的几条记录,然后再和其他表关联更多的字段
       第1、2种先把所有的字段 关联在一起,然后在从这些记录中选取有限的几条记录,
       第1、2种是否比第3种占用更多的内存
       特别是要关联某个表的大量字段的时候
    1、不会占用更多内存,其实第1种和第2种的写法基本上没什么区别,只是1是这样 select from a inner join b,而2 是 select from (a inner join b),两个语句,应该会有一样的执行计划的。2、第3种是先top 2,然后把结果集在和另外的2个表关联,这种思路是对的,先过滤数据,然后再关联,只是,比1和2,多关联了一次表,性能不一定好,还是得执行一下来比较。另外,你的3个语句,都可以进行简化,没必要用top 2,我以第1个语句作为例子:
    select * 
    from 
    (
    select sortval,id,pushtime,name,details 
    from 
    (
    select row_number()over(order by pushtime desc)as sortval,id,pushtime,name 
    from Tab_Push 
    inner join Tab_Info 
    on tarmac=@mac and Tab_Push.id = Tab_Info.id and Tab_Info.isenable=1
    ) A
    inner join Tab_infoEx on A.id = Tab_infoEx.id
    )B 
    where sortval > @sortval and sortval <= 2   --取前2条
    使用top 2和使用where sortval > @sortval and sortval <= @sortval + 2
    这两种方式在执行上或者效率上有什么差异?
      

  14.   


    1、第2种比第1种写法多用了一次select,是否在执行过程中会占用更多的内存,
     类似select xxx from (select ....)语句的执行过程问题,
       是否是先执行括号内的select然后把结果存在内存,
       之后再执行外层的select 2、第3种先定位有限的几条记录,然后再和其他表关联更多的字段
       第1、2种先把所有的字段 关联在一起,然后在从这些记录中选取有限的几条记录,
       第1、2种是否比第3种占用更多的内存
       特别是要关联某个表的大量字段的时候
    1、不会占用更多内存,其实第1种和第2种的写法基本上没什么区别,只是1是这样 select from a inner join b,而2 是 select from (a inner join b),两个语句,应该会有一样的执行计划的。2、第3种是先top 2,然后把结果集在和另外的2个表关联,这种思路是对的,先过滤数据,然后再关联,只是,比1和2,多关联了一次表,性能不一定好,还是得执行一下来比较。另外,你的3个语句,都可以进行简化,没必要用top 2,我以第1个语句作为例子:
    select * 
    from 
    (
    select sortval,id,pushtime,name,details 
    from 
    (
    select row_number()over(order by pushtime desc)as sortval,id,pushtime,name 
    from Tab_Push 
    inner join Tab_Info 
    on tarmac=@mac and Tab_Push.id = Tab_Info.id and Tab_Info.isenable=1
    ) A
    inner join Tab_infoEx on A.id = Tab_infoEx.id
    )B 
    where sortval > @sortval and sortval <= 2   --取前2条
    使用top 2和使用where sortval > @sortval and sortval <= @sortval + 2
    这两种方式在执行上或者效率上有什么差异?这样就不用排序了,因为top 2 后面有order by sortval ,这样直接过滤,就不用排序了
      

  15.   


    1、第2种比第1种写法多用了一次select,是否在执行过程中会占用更多的内存,
     类似select xxx from (select ....)语句的执行过程问题,
       是否是先执行括号内的select然后把结果存在内存,
       之后再执行外层的select 2、第3种先定位有限的几条记录,然后再和其他表关联更多的字段
       第1、2种先把所有的字段 关联在一起,然后在从这些记录中选取有限的几条记录,
       第1、2种是否比第3种占用更多的内存
       特别是要关联某个表的大量字段的时候
    1、不会占用更多内存,其实第1种和第2种的写法基本上没什么区别,只是1是这样 select from a inner join b,而2 是 select from (a inner join b),两个语句,应该会有一样的执行计划的。2、第3种是先top 2,然后把结果集在和另外的2个表关联,这种思路是对的,先过滤数据,然后再关联,只是,比1和2,多关联了一次表,性能不一定好,还是得执行一下来比较。另外,你的3个语句,都可以进行简化,没必要用top 2,我以第1个语句作为例子:
    select * 
    from 
    (
    select sortval,id,pushtime,name,details 
    from 
    (
    select row_number()over(order by pushtime desc)as sortval,id,pushtime,name 
    from Tab_Push 
    inner join Tab_Info 
    on tarmac=@mac and Tab_Push.id = Tab_Info.id and Tab_Info.isenable=1
    ) A
    inner join Tab_infoEx on A.id = Tab_infoEx.id
    )B 
    where sortval > @sortval and sortval <= 2   --取前2条
    使用top 2和使用where sortval > @sortval and sortval <= @sortval + 2
    这两种方式在执行上或者效率上有什么差异?变量有可能导致参数嗅探,但是也能提高计划重用
      

  16.   

    order by sortval  也要排序啊
      

  17.   


    我在想这个"其实就是两个两个表的关联的,再把关联的结果集,和第3个表关联"说法,
    sql内部会不会先把前两个表关联,然后得到部分结果集,比如该案例中就只需要把id记录下来,然后再和第3个表关联,得到最终的所有id,然后根据这些id把相应的字段提取到最终的结果集中
      

  18.   


    我在想这个"其实就是两个两个表的关联的,再把关联的结果集,和第3个表关联"说法,
    sql内部会不会先把前两个表关联,然后得到部分结果集,比如该案例中就只需要把id记录下来,然后再和第3个表关联,得到最终的所有id,然后根据这些id把相应的字段提取到最终的结果集中关联的时候,是按照id来关联的,但是在关联之前,肯定必须要去硬盘上把表的数据取出,放到内存,这个内存中的数据,不仅有id列,还有其他很多列,然后用id值进行关联,由于是在内存中,所以速度非常快,关联以后产生的结果集,然后再次和第3个表,进行关联的,最后按照select中指定的列,把数据返回。
      

  19.   

    多谢 阳泉酒家小当家、DBA_Huangzj 两位师兄的答疑解惑,
    现每人50分以表感谢
      

  20.   

    ad hoc,容易导致执行计划无法重用,使用参数化查询可以提高计划的重用率。但是由于优化器很多时候不知到你“将输入”什么参数值,这样会导致它只能使用统计信息的平均值来预估你的查询,而有些时候你传入的值应该是可以非常高效地查出来,但是由于取了平均值,对大表来说,可能只有扫描操作,这样性能就会下降。不知道这样描述你清不清楚