zoukankan      html  css  js  c++  java
  • Oracle 表的访问方式(1) ---全表扫描、通过ROWID访问表

    1.Oracle访问表的方式

      全表扫描、通过ROWID访问表、索引扫描

    2.全表扫描(Full Table Scans, FTS)

      为实现全表扫描,Oracle顺序地访问表中每条记录,并检查每一条记录是否满足WHERE语句的限制条件。ORACLE采用一次读入多个数据块(database block)的方式优化全表扫描,而不是只读取一个数据块,这极大的减少了I/O总次数,提高了系统的吞吐量,所以利用多块读的方法可以十分高效地实现全表扫描。需要注意的是只有在全表扫描的情况下才能使用多块读操作。在这种访问模式下,每个数据块只被读一次。

      使用FTS的前提条件:在较大的表上不建议使用全表扫描,除非取出数据的比较多,超过总量的5% -- 10%,或你想使用并行查询功能时。

    全表扫描实例(TABLE ACCESS FULL)

     1 --创建表并插入数据,并进行查询。
     2 
     3 --创建数据库
     4 SQL> create table t_captain
     5   2  (
     6   3     NO int,
     7   4     NAME VARCHAR2(32),
     8   5     WORKDAY DATE
     9   6  )
    10   7  /
    11 
    12 --创建序列
    13 SQL> CREATE SEQUENCE SEQ_USERINFO_NO
    14   2  INCREMENT BY 1   --每次加1
    15   3  START WITH 1     --从1开始计数
    16   4  /
    17 
    18 Sequence created.
    19 
    20 SQL>
    21 
    22 --插入100000条数据
    23 begin
    24   for i in 1..100000 loop
    25       INSERT INTO T_CAPTAIN VALUES(SEQ_USERINFO_NO.nextval,'captain',SYSDATE);
    26   end loop;
    27 end;
    28 /
    29 
    30 
    31 commit32 
    33 ----手动收集表的统计信息
    34 SQL> exec dbms_stats.gather_table_stats('NC60','T_CAPTAIN');
    35 
    36 PL/SQL procedure successfully completed.
    37 
    38 SQL> 
    39 
    40 
    41 --查询NO=5000的结果
    42 set autotrace traceonly  --只看查询计划
    43 select * from T_CAPTAIN where no = 5000;
    44 
    45 SQL> select * from T_CAPTAIN where no = 5000;
    46 
    47 
    48 Execution Plan
    49 ----------------------------------------------------------
    50 Plan hash value: 3680104071
    51 
    52 -------------------------------------------------------------------------------
    53 | Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    54 -------------------------------------------------------------------------------
    55 |   0 | SELECT STATEMENT  |           |     1 |    21 |   103   (1)| 00:00:02 |
    56 |*  1 |  TABLE ACCESS FULL| T_CAPTAIN |     1 |    21 |   103   (1)| 00:00:02 |
    57 -------------------------------------------------------------------------------
    58 
    59 Predicate Information (identified by operation id):
    60 ---------------------------------------------------
    61 
    62    1 - filter("NO"=5000)
    63 
    64 
    65 Statistics
    66 ----------------------------------------------------------
    67           1  recursive calls
    68           0  db block gets
    69         376  consistent gets
    70           0  physical reads
    71           0  redo size
    72         551  bytes sent via SQL*Net to client
    73         419  bytes received via SQL*Net from client
    74           2  SQL*Net roundtrips to/from client
    75           0  sorts (memory)
    76           0  sorts (disk)
    77           1  rows processed
    78 
    79 SQL> 

      从查询计划我们可以看到所采用的查询方式是“TABLE ACCESS FULL”。也正是因为采用全表扫描,所以consistent gets会大些

    3.通过ROWID访问表(table access by ROWID)

      ROWID指出了该行所在的数据文件、数据块以及行在该块中的位置,所以通过ROWID来存取数据可以快速定位到目标数据上,是Oracle存取单行数据的最快方法。为了通过ROWID存取表,Oracle 首先要获取被选择行的ROWID,或者从语句的WHERE子句中得到,或者通过表的一个或多个索引的索引扫描得到。Oracle然后以得到的ROWID为依据定位每个被选择的行。下面给出使用rowid访问表的实例。

    3.1.单个rowid的情形  

     1 --查看表上rowid
     2 SQL> select rowid,no,name from T_CAPTAIN where no < 10;
     3 
     4 ROWID                      NO NAME
     5 ------------------ ---------- --------------------------------
     6 AAAWOMAAGAAA//ZAAA          1 captain
     7 AAAWOMAAGAAA//ZAAB          2 captain
     8 AAAWOMAAGAAA//ZAAC          3 captain
     9 AAAWOMAAGAAA//ZAAD          4 captain
    10 AAAWOMAAGAAA//ZAAE          5 captain
    11 AAAWOMAAGAAA//ZAAF          6 captain
    12 AAAWOMAAGAAA//ZAAG          7 captain
    13 AAAWOMAAGAAA//ZAAH          8 captain
    14 AAAWOMAAGAAA//ZAAI          9 captain
    15 
    16 
    17 --根据rowid查询记录
    18 SQL> set autotrace on
    19 SQL> set line 200
    20 SQL> select rowid,no,name from T_CAPTAIN where rowid='AAAWOMAAGAAA//ZAAA';
    21 
    22 
    23 ROWID                      NO NAME
    24 ------------------ ---------- --------------------------------
    25 AAAWOMAAGAAA//ZAAA          1 captain
    26 
    27 
    28 Execution Plan
    29 ----------------------------------------------------------
    30 Plan hash value: 2487506745
    31 
    32 ----------------------------------------------------------------------------------------
    33 | Id  | Operation                  | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    34 ----------------------------------------------------------------------------------------
    35 |   0 | SELECT STATEMENT           |           |     1 |    21 |     1   (0)| 00:00:01 |
    36 |   1 |  TABLE ACCESS BY USER ROWID| T_CAPTAIN |     1 |    21 |     1   (0)| 00:00:01 |
    37 ----------------------------------------------------------------------------------------
    38 
    39 
    40 Statistics
    41 ----------------------------------------------------------
    42           0  recursive calls
    43           0  db block gets
    44           1  consistent gets
    45           0  physical reads
    46           0  redo size
    47         558  bytes sent via SQL*Net to client
    48         419  bytes received via SQL*Net from client
    49           2  SQL*Net roundtrips to/from client
    50           0  sorts (memory)
    51           0  sorts (disk)
    52           1  rows processed
    53 
    54 SQL>  

      查询计划中说明该查询是的表访问方式是”TABLE ACCESS BY USER ROWID“,也就是直接通过USER ROWID来访问,这也是为什么只需要1次consistent gets的原因。

    3.2.多个rowid的倾向

     1 SQL> select rowid,no,name from T_CAPTAIN where rowid in ('AAAWOMAAGAAA//ZAAG','AAAWOMAAGAAA//ZAAD','AAAWOMAAGAAA//ZAAI');
     2 
     3 ROWID                      NO NAME
     4 ------------------ ---------- --------------------------------
     5 AAAWOMAAGAAA//ZAAD          4 captain
     6 AAAWOMAAGAAA//ZAAG          7 captain
     7 
     8 
     9 Execution Plan
    10 ----------------------------------------------------------
    11 Plan hash value: 2350621837
    12 
    13 -----------------------------------------------------------------------------------------
    14 | Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
    15 -----------------------------------------------------------------------------------------
    16 |   0 | SELECT STATEMENT            |           |     1 |    21 |     1   (0)| 00:00:01 |
    17 |   1 |  INLIST ITERATOR            |           |       |       |            |          |
    18 |   2 |   TABLE ACCESS BY USER ROWID| T_CAPTAIN |     1 |    21 |     1   (0)| 00:00:01 |
    19 -----------------------------------------------------------------------------------------
    20 
    21 
    22 Statistics
    23 ----------------------------------------------------------
    24           1  recursive calls
    25           0  db block gets
    26           2  consistent gets
    27           0  physical reads
    28           0  redo size
    29         621  bytes sent via SQL*Net to client
    30         419  bytes received via SQL*Net from client
    31           2  SQL*Net roundtrips to/from client
    32           0  sorts (memory)
    33           0  sorts (disk)
    34           2  rows processed
    35 
    36 SQL>

    查询计划分析:

    1.上面的执行计划中出现了INLIST ITERATOR,即INLIST迭代,该操作说明其子操作多次重复时,会出现该操作。 

    2.由于我们使用了in运算,且传递了2个rowid,故出现INLIST迭代操作

    3.迭代操作意味着条件中的对象列表一个接一个的迭代传递给子操作

    4.此时统计信息中的consistent gets为2,并不是因为传入的rowid有2个,假如传入的rowid有4个,consistent gets也等于2。

    注意:使用ROWID进行查询的前提是我们明确知道了一个正确的ROWID,然后通过这个ROWID进行查询。所以这里所提到的所有ROWID 必须是真实存在的,否则会报错。

    整理自网络

  • 相关阅读:
    Infopath Notify 弹出提示信息
    window.showModalDialog 返回值
    【转】获得正文内容中的所有img标签的图片路径
    Json Datable Convert
    Sharepoint 列表 附件 小功能
    Surgey 权限更改
    SQL 触发器用于IP记录转换
    Caml语句 查询分配给当前用户及当前组
    jquery 1.3.2 auto referenced when new web application in VSTS2010(DEV10)
    TFS diff/merge configuration
  • 原文地址:https://www.cnblogs.com/polestar/p/4131642.html
Copyright © 2011-2022 走看看