Oracle11g 带分页的选择查询

Posted

技术标签:

【中文标题】Oracle11g 带分页的选择查询【英文标题】:Oracle11g select query with pagination 【发布时间】:2021-11-01 01:18:35 【问题描述】:

在尝试从 oracle11g 数据库中获取具有分页的对象列表时,我遇到了一个很大的性能问题。

据我所知并在网上查到,在 oracle11g 中实现分页的唯一方法如下: 示例:[page=1, size=100]

SELECT * FROM
  (
    SELECT pagination.*, rownum r__  FROM
      (
         select * from "TABLE_NAME" t
         inner join X on X.id = t.id
         inner join .....
         where ......
         order
      ) pagination
    WHERE rownum <= 200 
  )
WHERE r__ > 100

这个查询的问题是,从表“TABLE_NAME”中获取数据的最内部查询返回了大量数据,导致整个查询需要 8 秒(应用后返回大约 200 万条记录) where 子句,它包含 9 或 10 个 join 子句)。

这样做的原因是,最内部的查询是获取所有尊重 where 子句的数据,然后第二个查询获取 200 行,第三个查询排除前 100 行以获取第二页的数据需要。

难道没有办法在一个查询中做到这一点,即无需执行所有这些步骤并导致性能问题就可以获取我们需要的第二页数据吗?

谢谢!!

【问题讨论】:

这能回答你的问题吗:***.com/questions/241622/paging-with-oracle 【参考方案1】:

这取决于您的排序选项 (order by ...):由于您的 order by 子句,数据库需要在应用外部 where rownum&lt;200 之前对整个数据集进行排序。

如果您删除 order by 子句,它将仅获取 200 行。在某些情况下,oracle 可以避免排序操作(例如,如果 oracle 可以使用某些索引以所需的顺序获取请求的数据)。顺便说一句,Oracle 在rownum&lt;N 谓词的情况下使用优化的排序操作:它不会对整个数据集进行排序,它只是获取前 N 条记录。

您可以使用排序跟踪事件更深入地调查排序操作:alter session set events '10032 trace name context forever, level 10';

此外,有时最好使用分析函数,例如

select *
from (
   select
      t1.*
     ,t2.*
     ,row_number()over([partition by ...] order by ...) rn
   from t1
       ,t2
   where ...
   )
where rn <=200
and rn>=100

因为在某些特定情况下,Oracle 可以转换您的查询以将排序和排序过滤谓词推送到尽可能早的步骤。

【讨论】:

以上是关于Oracle11g 带分页的选择查询的主要内容,如果未能解决你的问题,请参考以下文章

带分页样式的thinkphp数据查询

带分页的 Ajax 搜索 [Laravel]

带分页的sql语句

Rails 4 - 带分页的数据表

使用带分页的php进行高级搜索?

一个类别和带分页的可多选表格的实现方案