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是不同的。

  • 相关阅读:
    今天 弄了一下ajax 里面的
    重修理解了一下js 控制treeview 菜单的子级和父级的关系 理解的还不够全 因为 html不够全 但是加个注释吧
    xml .net 用法
    这几天在做把数据库里的数据 导出 并且压缩 学到了一些东西
    今天实现了用按钮后台动态实现了 table里面内容的显示和隐藏 在实现过程中了解了updatepanel的简单的用法
    今天第一次参加了软件产品的讨论会议 收获
    收藏个debug的文章
    Animate.css
    flash遨游缓存问题
    URL短地址压缩算法 微博短地址原理解析 (Java实现)
  • 原文地址:https://www.cnblogs.com/handhead/p/13889970.html
Copyright © 2011-2022 走看看