Oracle分页查询中排序与效率问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle分页查询中排序与效率问题相关的知识,希望对你有一定的参考价值。

参考技术A

  原始未分页查询Sql代码如下  

  select ROWNUM rn t id ID o name YYB u name XM t MC from tZDYSX   t tuser u lbanization o where t cjr=u id and id=code and t gx =    order by ID 

  结果如下 RN    ID      YYB       XM     MC        某证券总部     管理员 测试      某证券总部     管理员 持有上港 股以上     某证券总部     管理员 十年规划    某证券总部     管理员 开发渠道为上海    某证券总部     管理员 万科A    某证券总部     管理员    某证券总部     管理员 今天过生日的客户      某证券总部     管理员 客户状态正常     某证券总部     管理员 无交易    某证券总部     管理员 OA     某证券总部     管理员 幸运客户    某证券总部     管理员 风险型    某证券总部     管理员 tst    白沙网上交易   安昌彪 安客户正常     某证券总部     管理员    某证券总部     管理员 客户号包含    某证券总部     管理员 aaa    某证券总部     管理员 ssssssss    某证券总部     管理员    某证券总部     管理员    某证券总部     管理员    某证券总部     管理员 aaaaaa

   rows selected

  最初我使用如下Sql代码查询  

  select * from (select ROWNUM rn t id ID o name YYB u name XM t MC    from tZDYSX t tuser u lbanization o where t cjr=u id and id=code and    t gx = order by t ID )Where rn> and rn<= ; 

  这种方法能成功分页 结果如下 RN    ID        YYB       XM      MC    某证券总部     管理员 开发渠道为上海    某证券总部     管理员 万科A    某证券总部     管理员    某证券总部     管理员 今天过生日的客户    某证券总部     管理员 客户号包含    某证券总部     管理员 aaa    某证券总部     管理员 ssssssss    某证券总部     管理员    某证券总部     管理员    某证券总部     管理员 aaaaaa

   rows selected

  从结果看来 有个问题 此语句Sql代码 order by CJSJ DESC  被执行 但是是在分后的第 到 条记录的结果集中再进行排序 而不是先排序后分页 (本来希望显示ID为 到 结果变为 到 )

  后来变为以下Sql代码查询  

  SELECT *    FROM(    SELECT ROWNUM RN TA *    FROM(   select t id ID o name YYB u name XM t MC   from tZDYSX t tuser u lbanization o    where t cjr=u id and id=code and t gx = order by t ID   )TA WHERE ROWNUM <=    )WHERE RN >   SELECT * FROM( SELECT ROWNUM RN TA * FROM(select t id ID o name YYB u name XM t MCfrom tZDYSX t tuser u lbanization o where t cjr=u id and id=code and t gx = order by t ID)TA WHERE ROWNUM <= )WHERE RN >

  结果如下 RN    ID     YYB           XM     MC    某证券总部     管理员 幸运客户    某证券总部     管理员 风险型    某证券总部     管理员 tst    白沙网上交易   安昌彪 安客户正常    某证券总部     管理员    某证券总部     管理员 客户号包含    某证券总部     管理员 aaa    某证券总部     管理员 ssssssss    某证券总部     管理员    某证券总部     管理员

   rows selected

  看来结果是正确的

  总结 第二种方法其中最内层的查询Sql代码

  

  select t id ID o name YYB u name XM t MC   from tZDYSX t tuser u lbanization o    where t cjr=u id and id=code and t gx = order by t ID 

  表示不进行翻页的原始查询语句 ROWNUM <= 和RN > 控制分页查询的每页的范围 第二种方法在大多数情况拥有较高的效率 分页的目的就是控制输出结果集大小 在上面的分页查询语句中 这种考虑主要体现在WHERE ROWNUM <= 这句上

  选择第 到 条记录存在两种方法 第二种方法正是在查询的第二层通过ROWNUM <= 来控制最大值 在查询的最外层控制最小值 而第一种方法是去掉查询第二层的WHERE ROWNUM <= 语句 在查询的最外层控制分页的最小值和最大值

  一般来说 第二个查询的效率比第一个高得多 这是由于CBO 优化模式下 Oracle可以将外层的查询条件推到内层查询中 以提高内层查询的执行效率 对于第二个查询语句 第 层的查询条件WHERE ROWNUM <= 就可以被Oracle推入到内层查询中 这Oracle查询的结果一旦超过了ROWNUM限制条件 就终止查询将结果返回了

  而第一个查询语句 由于查询条件Where rn> and rn<= 是存在于查询的第三层 而Oracle无法将第三层的查询条件推到最内层(即使推到最内层也没有意义 因为最内层查询不知道RN代表什么) 因此 对于第一个查询语句 Oracle最内层返回给中间层的是所有满足条件的数据 而中间层返回给最外层的也是所有数据 数据的过滤在最外层完成 显然这个效率要比第二个查询低得多

lishixinzhi/Article/program/Oracle/201311/18330

oracle分页详解(rownum与orderby)

参考技术A

  Oracle的分页是通过rownum实现的

  rownum是一个伪列 是oracle系统自动为查询返回结果的每行分配的编号 第一行为 第二行为 以此类推

  一个oracle分页 至少要包含三层(除非不用order by 暂时可以用 层实现) 模板为

  select temp * from(

  select rownum num temp * from(

  SQL查询

  ) temp where rownum<=n

  )temp    where temp num>n

  例如 值返回查询结果第 条到 条著 条的信息的SQL如下

  select temp *

  from(

  select rownum num temp *

  from(

  select tt title_id tt name

  from t_title tt

  where tt name like %美%

  order by tt sort_seqs asc tt title_Id desc) temp

  where rownum<=

  )temp

  where temp num>

  分析

   首先是一个正常的查询语句(包含order by)

  select tt title_id tt name

  from t_title tt

  where tt name like %美%

  order by tt sort_seqs asc tt title_Id desc

  这个和正常的SQL语句没有任何的区别

   添加rownum字段 显示列数

  select rownum num temp *

  from(

  select tt title_id tt name

  from t_title tt

  where tt name like %美%

  order by tt sort_seqs asc tt title_Id desc) temp

  where rownum<=

  我们添加了rownum 显示字段 这时候就会会每行添加一个行数的编号 并且只返回 条之前的数据(包含 条)

   截取第 条到 条的数据 SQL就是上面最完整的那个啦

  使用精解

   rownum的使用

  如下两条语句

  select rownum id name from student where rownum> ;

  select rownum id name from student where rownum<= ;

  第一条语句的执行结果为空 第二条语句的执行结果为前 条记录

  为什么会这样呢 我们知道rownum是伪列 是oracle为查询结果自动添加的伪列 第一行是 如果where rownum> 这时候查找第一条发现它的rownum= 不满足条件 于是抛弃掉 把第二条语句的rownum赋值为 再判断第二条记录是否满足条件 同样不满足 于是发生了死循环一样的判断 最终返回空

  有人这时候就奇怪啦 为什么第一条记录rownum= 不满足条件时候 第二条记录rownum= 却要重新设值为 呢 非常简单 你直接在where后添加了条件rownum> 它是个条件啦 第一条记录不满足条件 叫抛弃掉啦 这时候结果集是空的 当然会一直rownum= 的赋值

  解决办法:先查询 并为每条记录分配rownum 然后嵌套查询

  select t * from (select rownum num id name from student) t where t num>

  第二条语句可以正常的执行 根据上面的解释 这个可以理解了吧!

   rownum与order by同时存在的问题

  当 where 后面有rownum的判断 并且存在order by时候 rownum的优先级高!

  oracle会先执行rownum的判断 然后从结果中order by 很明显是错误的结果啦!就好像学校要取成绩最好的前 名同学 结果这种方法一执行 成了取出 名同学 然后按照成绩的高低排序!

  这点与SQL Server的TOP完全不同 TOP遇上order by 是先执行order by 在分页的

lishixinzhi/Article/program/Oracle/201311/17827

以上是关于Oracle分页查询中排序与效率问题的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 分页查询在子查询中使用了 排序和like 会影响效率吗? 怎样优化呢

oracle的分页处理,oracle中针对一个一千条记录的表如果要查200到300的记录怎么查

Oracle分页查询排序数据重复问题

oracle 分页查询重复问题

ORACLE分页查询SQL语句(最有效的分页)

ORACLE分页查询SQL语法——高效的分页