zoukankan      html  css  js  c++  java
  • oracle优化-分页查询的错误认识

    对于分页查询,上一篇文章总结了实现分页查询的办法。同时给出等价写法,另外在执行计划角度验证SQL的等价性https://www.cnblogs.com/handhead/p/13856505.html
    分页查询的错误认识是由分页查询等价改写引申出的。下面我们先构造测试表,给出分页查询的等价写法,通过SQL的代价验证SQL的错误认识。

    SQl在业务层面要求:取测试表TEST_A,status=5的记录,按sysid排序,展示3000-4000行;

    1、测试表及说明

    1、创建测试表
    SQL>CREATE TABLE TEST_A(ID NUMBER NOT NULL,SYSID NUMBER,STATUS NUMBER,INFO VARCHAR2(2000));
    SQL>INSERT INTO TEST_A
    SELECT ROWNUM,ROWNUM+1,TRUNC(DBMS_RANDOM.VALUE(1,9)) ,RPAD('*',2000,'*') FROM DUAL CONNECT BY ROWNUM<=100000;
    SQL> ALTER table test_a add primary key(id);
    SQL>create index ind_status_sysid on test_a(status,sysid);
    说明:TEST_A中ID是主键,status字段取值[1,8]且均匀分布。
    要求:取TEST_A中status=5的记录,按sysid排序,展示3000-4000行
    View Code

    2、分页查询的等价写法

    ①:两层嵌套分页查询
    select * from (select row_number()over(order by sysid) rn,t.* from test_a t where status=5) where rn between 3000 and 4000;
    ②、三层嵌套分页查询
    select * from 
        (select rownum rn ,t.* from 
            (select * from test_a  where status=5 order by sysid )t
        where rownum<=4000) 
    where rn >=3000;

    3、分页查询的错误认识

    *****************************************************错误认识1******************************************************************************
    等价其实不等价
    SQL1:select /*+gather_plan_statistics*/* from (select row_number()over(order by sysid) rn,t.* from test_a t where status=5) where rn between 3000 and 4000;

    SQL2:select /*+gather_plan_statistics*/* from (select rownum rn,t.* from test_a t where status=5 order by sysid) where rn between 3000 and 4000;

    认为SQL1与SQL2等价,其实这种认识是错误,我们从执行计划验证错误性,查看SQL1的执行计划

    查看SQL2的执行计划:

    从上述的执行计划我们看到同样是INDEX RANGE SCAN,SQL1实际访问了4000条记录,SQL2实际访问了12452条记录;对于逻辑读,SQL1是3608个数据块,SQL2是11065个数据块。推出SQL1与SQL2不等价。

    **********************************************************错误认识2**********************************************************************************
    分页查询每页的cost,buffer是一样的!这是不对的,是错误认识
    SQL3:select /*+gather_plan_statistics*/* from (select row_number()over(order by sysid) rn,t.* from test_a t where status=5) where rn between 1 and 1000;

    SQL4:select /*+gather_plan_statistics*/* from (select row_number()over(order by sysid) rn,t.* from test_a t where status=5) where rn between 3000 and 4000;

    SQL5:select /*+gather_plan_statistics*/* from (select row_number()over(order by sysid) rn,t.* from test_a t where status=5) where rn between 10000 and 11000;

    对于分页查询我们发现查询1-1000行,3000-4000行,10000-11000行,IND_STATUS_SYSID实际返回数量是不同的。会造成耗时时间不同,buffers不同,cost是由于物理读决定的,实际返回数量不同物理读肯定也大不相同。最终推出SQL3,SQL4,SQL5是不同的。

  • 相关阅读:
    VOA 2009/11/02 DEVELOPMENT REPORT In Kenya, a Better Life Through Mobile Money
    2009.11.26教育报道在美留学生数量创历史新高
    Java中如何实现Tree的数据结构算法
    The Python Tutorial
    VOA HEALTH REPORT Debate Over New Guidelines for Breast Cancer Screening
    VOA ECONOMICS REPORT Nearly Half of US Jobs Now Held by Women
    VOA ECONOMICS REPORT Junior Achievement Marks 90 Years of Business Education
    VOA 2009/11/07 IN THE NEWS A Second Term for Karzai; US Jobless Rate at 10.2%
    Ant入门
    Python 与系统管理
  • 原文地址:https://www.cnblogs.com/handhead/p/13889970.html
Copyright © 2011-2022 走看看