从结尾(文件)开始读取查询中的数据

时间:2014-02-21 14:33:50

标签: sql plsql oracle11g

我想从一张非常大的表中检索(100)最近的日期。这似乎很容易,但是使用这样的东西;

SELECT *
FROM (
     SELECT *
     FROM   [table] tbl
     WHERE  [some conditions]
     ORDER  BY tbl.date
     )
WHERE ROWNUM < 100;

效率非常低,因为整个表都是读取和排序的。

最近的日期可能(但不能保证)在表的末尾。现在,出于性能原因,我想采取f.e.表的最后1000行满足设置条件并处理它们,而不访问巨大的表的其余部分。

我想知道是否可以通过优化器提示或其他方式使SQL(或PL / SQL)代码从文件末尾开始读取表,并让它停止查询只要选择(fe)1000行?(与将WHEN ROWNUM < 1000添加到简单选择时查询停止的方式相同)

1 个答案:

答案 0 :(得分:0)

如果tbl.date上有索引且(此列不可为空,或者您指定WHERE子句中只要不是空值)并且统计信息是最新的,那么索引应该是使用。

在大多数情况下,这种查询会获得INDEX FULL SCAN ASC/DESCENDING访问路径,如下所示:

SQL> CREATE TABLE TEST AS
  2  (SELECT SYSDATE + ROWNUM dt, RPAD('x', 100, 'x') DATA
  3    FROM dual CONNECT BY LEVEL <= 1E5);

Table created

SQL> CREATE INDEX test_idx ON TEST(dt);

Index created

SQL> EXPLAIN PLAN FOR
  2  SELECT *
  3    FROM (SELECT *
  4            FROM TEST
  5           WHERE dt IS NOT NULL
  6           ORDER BY dt DESC)
  7  WHERE ROWNUM <= 100;

Explained

SQL> SELECT * FROM table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3326882503
--------------------------------------------------------------------------------
| Id  | Operation                     | Name     | Rows  | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |          |   100 |  6100 |     4   (0)|
|*  1 |  COUNT STOPKEY                |          |       |       |            |
|   2 |   VIEW                        |          | 93692 |  5581K|     4   (0)|
|   3 |    TABLE ACCESS BY INDEX ROWID| TEST     | 93692 |  5581K|     4   (0)|
|*  4 |     INDEX FULL SCAN DESCENDING| TEST_IDX |   100 |       |     2   (0)|
--------------------------------------------------------------------------------

此访问路径提供您正在查找的算法:向前或向后读取索引,直到返回所需的行数。

如果您没有获得此访问路径,可能是因为您正在搜索非索引值(NULLS),或者存在优化认为更有效的另一个访问路径。