zoukankan      html  css  js  c++  java
  • Max(rowid)是否走B树索引

    Max(rowid)是否走B树索引

    测试:SQL文本Max(rowid)执行计划是否走B树索引测试

    一、猜测执行计划

    SQL语句中,执行max(rowid)时,执行计划猜测:

    AB树索引全索引范围扫描

    BB树索引根--叶块扫描

    C不走索引,全表扫描

    二、测试

    1#测试用户scott,查询索引信息:

    SQL>select INDEX_NAME,INDEX_TYPE,UNIQUENESS,TABLE_OWNER,TABLE_NAME from user_indexes where table_owner='SCOTT' and table_name='EMP'

    INDEX_NAME INDEX_TYPE UNIQUENES TABLE_OWNE TABLE_NAME

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

    PK_EMP     NORMAL     UNIQUE    SCOTT      EMP

    2#SQL文本

    SQL> select * from emp where rowid=(select max(rowid) from emp);

    SQL> select max(rowid) from emp;

    MAX(ROWID)

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

    AAAVREAAEAAAACXAAN

    3#执行计划工具autotrace

    SQL> set autotrace traceonly

    SQL> select max(rowid) from emp;

    | Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time       

    |   0 | SELECT STATEMENT  |        |     1 |    12 |     1   (0)| 00:00:01

    |*  1 |  FILTER         

    |   2 |   SORT AGGREGATE  |        |     1 |    12

    |   3 |    INDEX FULL SCAN| PK_EMP |    14 |   168 |     1   (0)| 00:00:01

    #走的是索引范围全扫描 猜想中执行计划的A

    SQL> select count(*) from scott.emp;  --索引范围全扫描!

      COUNT(*)

    ----------

            14

    4#小结

    max(rowid)走的是索引范围扫描

    三、需求改写

    #如下:本次有一个SQL语句,查询max(rowid)寻找一行数据,查询这行数据的所有记录

    1#SQL文本

    SQL> select * from emp where rowid=(select max(rowid) from emp)

    2#执行计划:

    SQL> select * from emp where rowid=(select max(rowid) from emp)

    | Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time

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

    |   0 | SELECT STATEMENT        |        |     1 |    38 |     2   (0)| 00:00:01

    |*  1 |  FILTER                

    |   2 |   TABLE ACCESS BY USER ROWID| EMP    |     1 |    38 |     1   (0)| 00:00:01

    |*  3 |    FILTER              

    |   4 |     SORT AGGREGATE          |        |     1 |    12     

    |   5 |      INDEX FULL SCAN        | PK_EMP |    14 |   168 |     1  (0)| 00:00:01

    Statistics

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

              4  recursive calls

             30  db block gets

              6  consistent gets

    3#改写SQL

    #改写SQL文本:

    #需求SQL改写:使用主键empno

    #改写SQL最重要的是等价,查询过滤的数据是相同的,这样改写SQL才算优化,否则等同重新定义SQL,不能叫优化SQL,而是重写SQL

    #改写前 : 使用max(rowid)提取行记录

    SQL> select empno from scott.emp where rowid=(select max(rowid) from scott.emp);

         EMPNO

    ----------

          7934

    #改写后:使用max(empno)提取行记录:

    SQL> select max(empno) from scott.emp;

    MAX(EMPNO)

    ----------

          7934

    #查询的数据等价:SQL文本如下

    SQL> select * from emp where empno=(select max(empno) from emp)

    #改写SQL,查看执行计划:

    SQL> select * from emp where empno=(select max(empno) from emp)

    | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time   

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

    |   0 | SELECT STATEMENT                1 |    38 |     1   (0)| 00:00:01

    |*  1 |  FILTER            

    |   2 |   TABLE ACCESS BY INDEX ROWID | EMP   1  |  38 |     1   (0)| 00:00:01 |

    |*  3 |    INDEX UNIQUE SCAN      PK_EMP |    1 |   |     0   (0)| 00:00:01 |

    |   4 |     SORT AGGREGATE            |        |     1 |     4 |     

    |   5 |      INDEX FULL SCAN (MIN/MAX)| PK_EMP |     1  |    4 |  1   (0)| 00:00:01

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

    Statistics

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

              2  recursive calls

             15  db block gets

              5  consistent gets

    #对比:

    1.执行计划方式对比:

    虽然从结果对比数据没有明显差异,但是从细节看,其实SQL已经优化了:

    从执行计划序列号5看:

    改写后是 INDEX FULL SCAN (MIN/MAX)| PK_EMP |     1  查询一行数据、  

    改写前是 INDEX FULL SCAN        | PK_EMP |    14  

    #从索引扫描方式改变了:一个是索引唯一值查询,一个是索引全扫描,带来的就是数据量变小

    2.查询数据量对比:

    但是最终为何没有看到明显的差异,是由于测试的表数据量过小,导致成本优化后差异量少

    #本次为啥没有看到直观差异,改写后

     请看执行计划序列号二步TABLE ACCESS BY INDEX ROWID | EMP   1 row  |  38 bytes

       改写前: TABLE ACCESS BY USER ROWID| EMP    |     1 bytes|    38   bytes

    #不管是优化前SQL索引全扫描,还是优化后索引唯一扫描,暂且放下,因为最终从索引找到了唯一的一行数据,ROWID,可以直接从存储对象中,找到数据块。

      Oracle读取数据,最小单元以块为单位,因此,实质上,本次优化SQL,修改的是索引范围全扫描,修改为索引唯一扫描,节省的是索引查询的时间

  • 相关阅读:
    Mybatis 持久层框架
    spring beans文件
    java_抽象类&抽象方法
    java——类
    python 安装 HTMLtestRunner
    pychram永久激活
    unittest单元测试框架
    pandas常用函数
    linux 下分别使用pip2、pip3
    linux 下切换Python版本(某用户,共存,替换)
  • 原文地址:https://www.cnblogs.com/lvcha001/p/9094409.html
Copyright © 2011-2022 走看看