zoukankan      html  css  js  c++  java
  • FIRST_ROWS和ALL_ROWS的區別和作用

    first_rows是最佳响应速度设计的,不能说返回一条记录,这样说是错误的。

    all_rows是为了最佳吞吐量,也不能说是all_rows倾向与采用全表扫描,其实默认情况下都是all_rows的。

    给一个例子:

     

     

    代码:


     

    SQL> create index ind_page_test_id on page_test(id);

    Index created

    SQL> analyze index ind_page_test_id compute statistics;

    Index analyzed

    SQL>select * from (

      2      select rownum rn,a.object_name

      3      from page_test a,

      4           page_test b,

      5           page_test c

      6      where a.id=b.id

      7      and b.id=c.id

      8      and rownum<=5

      9*     ) where rn>0

    已用时间:  00: 00: 02.09

    Execution Plan

    ----------------------------------------------------------

       0      SELECT STATEMENT Optimizer=CHOOSE (Cost=2473 Card=5 Bytes=395)

       1    0   VIEW (Cost=2473 Card=5 Bytes=395)

       2    1     COUNT (STOPKEY)

       3    2       HASH JOIN (Cost=2473 Card=831104 Bytes=23270912)

       4    3         HASH JOIN (Cost=765 Card=831104 Bytes=6648832)

       5    4           INDEX (FAST FULL SCAN) OF 'IND_PAGE_TEST_ID' (NON-UNIQUE) (Cost=180 Card=831104 Bytes=3324416)

       6    4           INDEX (FAST FULL SCAN) OF 'IND_PAGE_TEST_ID' (NON-UNIQUE) (Cost=180 Card=831104 Bytes=3324416)

       7    3         TABLE ACCESS (FULL) OF 'PAGE_TEST' (Cost=1051 Card=831104 Bytes=16622080)

    Statistics

    ----------------------------------------------------------

              0  recursive calls

              0  db block gets

           3725  consistent gets

              0  physical reads

              0  redo size

              ……

    SQL> select * from (

      2      select /*+ first_rows */

      3      rownum rn,a.object_name

      4      from page_test a,

      5           page_test b,

      6           page_test c

      7      where a.id=b.id

      8      and b.id=c.id

      9      and rownum<=5

    10     ) where rn>0;

    已用时间:  00: 00: 01.01

    Execution Plan

    ----------------------------------------------------------

       0      SELECT STATEMENT Optimizer=HINT: FIRST_ROWS (Cost=1666362 Card=5 Bytes=395)

       1    0   VIEW (Cost=1666362 Card=5 Bytes=395)

       2    1     COUNT (STOPKEY)

       3    2       NESTED LOOPS (Cost=1666362 Card=831104 Bytes=23270912)

       4    3         NESTED LOOPS (Cost=1666362 Card=831104 Bytes=19946496)

       5    4           INDEX (FULL SCAN) OF 'IND_PAGE_TEST_ID' (NON-UNIQUE) (Cost=1852 Card=831104 Bytes=3324416)

       6    4           TABLE ACCESS (BY INDEX ROWID) OF 'PAGE_TEST' (Cost=3 Card=1 Bytes=20)

       7    6             INDEX (RANGE SCAN) OF 'IND_PAGE_TEST_ID' (NON-UNIQUE) (Cost=2 Card=1)

       8    3         INDEX (RANGE SCAN) OF 'IND_PAGE_TEST_ID' (NON-UNIQUE) (Cost=2 Card=1 Bytes=4)

    Statistics

    ----------------------------------------------------------

              0  recursive calls

              0  db block gets

             35  consistent gets

              0  physical reads

              0  redo size

            

     


     

    从这里我们可以看到,使用first_rows是查询的逻辑读降低到了只有35个,而且响应速度也变的更快,我们进一步观察其执行时间:

     

     

    代码:


     

    SQL>set autot off        

    SQL>select * from (

      2      select rownum rn,a.object_name

      3      from page_test a,

      4           page_test b,

      5           page_test c

      6      where a.id=b.id

      7      and b.id=c.id

      8      and rownum<=5

      9*     ) where rn>0

         ……

    已用时间:  00: 00: 01.08

    SQL> select * from (

      2      select /*+ first_rows */

      3      rownum rn,a.object_name

      4      from page_test a,

      5           page_test b,

      6           page_test c

      7      where a.id=b.id

      8      and b.id=c.id

      9      and rownum<=5

    10     ) where rn>0;

    ……

    已用时间:  00: 00:

     


     

    可以看到,而且实行时间几乎为0。这个是一个比较好的结果,表示采用forst_rows提示起到了很好的效果,因为forst_rows在没有索引的表上关联是不合适的,而且根据forst_rows提示的功能,是为了满足最快反应速度,也就是说对开始的页面返回速度很快,但是对后面的行返回速度很慢,我们就来测试一下。

     

     

    代码:


     

    SQL>select * from (

      2      select rownum rn,a.object_name

      3      from page_test a,

      4           page_test b,

      5           page_test c

      6      where a.id=b.id

      7      and b.id=c.id

      8      and rownum<=5005

      9*     ) where rn>5000

    ……

    已用时间:  00: 00: 01.08

    SQL> select * from (

      2      select /*+ first_rows */

      3      rownum rn,a.object_name

      4      from page_test a,

      5           page_test b,

      6           page_test c

      7      where a.id=b.id

      8      and b.id=c.id

      9      and rownum<=5005

    10     ) where rn>5000;

    ……

    已用时间:  00: 00: 00.00

    SQL> select * from (

      2      select rownum rn,a.object_name

      3      from page_test a,

      4           page_test b,

      5           page_test c

      6      where a.id=b.id

      7      and b.id=c.id

      8      and rownum<=50005

      9      ) where rn>50000;

    ……

    已用时间:  00: 00: 01.09

    SQL> select * from (

      2      select /*+ first_rows */

      3      rownum rn,a.object_name

      4      from page_test a,

      5           page_test b,

      6           page_test c

      7      where a.id=b.id

      8      and b.id=c.id

      9      and rownum<=50005

    10     ) where rn>50000;

    ……

    已用时间:  00: 00: 00.07

    SQL> select * from (

      2      select rownum rn,a.object_name

      3      from page_test a,

      4           page_test b,

      5           page_test c

      6      where a.id=b.id

      7      and b.id=c.id

      8      and rownum<=500005

      9      ) where rn>500000;

    ……

    已用时间:  00: 00: 02.06

    SQL> select * from (

      2      select /*+ first_rows */

      3      rownum rn,a.object_name

      4      from page_test a,

      5           page_test b,

      6           page_test c

      7      where a.id=b.id

      8      and b.id=c.id

      9      and rownum<=500005

    10     ) where rn>500000;

    ……

    已用时间:  00: 00: 07.07

    .

     


     

    通过不同的测试,可以看到,在开始部分,增加提示的速度明显要比不增加提示要快,但是,随着往后翻页,速度会越来越慢。幸好的是,大部分的用户只对前面的数据敢兴趣,所以增加前面部分的分页速度是很重要的。其实还可以通过程序转换的方式,即前面的分页查询使用hint提示,而后面部分则使用普通的分页查询。或者,对于很多条记录的分页查询,根本就没有最后一页这样显示最后部分的按钮,类似google,可以一次显示依次的10个页面。

     

     

     

    从本质上说,FIRST_ROWS和ALL_ROWS是通过提示影响Oracle执行计划的选择,从而提供不同的查询响应。

    通常FIRST_ROWS模式下,Oracle倾向于使用NL来进行表连接,NL通过驱动表逐层析取内层表,可以边执行边输出,也就实现了通常所说的,以尽快地速度返回(第一条)结果。也就是最小化立即响应时间。

    而ALL_ROWS模式下,Oracle倾向于使用HASH JOIN来进行表连接,HASH JOIN需要首先在RAM中构造HASH表,返回第一条记录必须等待这个HASH TABLE构造完毕,从而返回第一条记录的时间会晚于NL。而ALL_ROWS通常会有更好的成本,从而可能使总体执行时间更短

  • 相关阅读:
    Lazarus中system.length说明
    Lazarus中TScreen类使用介绍
    Delphi深度探索-CodeSite应用指南
    Lazarus如何变成XE的界面
    Lazarus IDE的几个小技术
    Delphi结构体数组指针的问题
    delphi动态数组指针问题
    delphi 数组类型与数组指针的巧妙利用
    Delphi Form的释放和隐藏:free,hide,close
    Delphi 记录类型- 结构指针
  • 原文地址:https://www.cnblogs.com/wuxi/p/2740397.html
Copyright © 2011-2022 走看看