0

重複の可能性:
Oracleはrownumを評価する前にすべての行をフェッチしますか?

10万行のテーブルで次のクエリを実行すると

select * from 
(
 select rownum rownumber, fname, lastname
 from customers
) where rownumber between 1 and 100;

Oracleはすべての100kをフェッチしてから、フェッチされた行のリストをフィルタリングして最初の100を取得しますか、それともすべての100k行をフェッチせずに最初の100にフィルタリングする賢い方法がありますか?

上記の例で、Oracleが実際にフェッチを実行する方法を見つける方法はありますか?

4

1 に答える 1

3

まず、内部クエリはどのような順序付けも行っていないため、クエリは任意の100行を返します。これが結果をページングするクエリを作成しようとしている場合、これは効率的ではなく、正しくないため、適切なアプローチではありません。返される行のセットは時間の経過とともに変化する可能性があり、行は結果の多くの異なるページに簡単に表示されるか、ページがまったく表示されません。

ただし、クエリプランを確認することで、フィルタがいつ適用されるかを確認するのは簡単です。FOO100,000行の簡単なテーブルを作成します

SQL> drop table foo;

Table dropped.

SQL> create table foo
  2  as
  3  select level col1
  4    from dual
  5   connect by level <= 100000;

Table created.

次に、自動トレースを有効にし、実際のデータの表示を抑制して、クエリを実行します

SQL> set autotrace traceonly;

SQL> select *
  2    from (select rownum rn, col1
  3            from foo)
  4   where rn between 1 and 100;

100 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 3193632835

----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |   101K|  2577K|    47   (3)| 00:00:01 |
|*  1 |  VIEW               |      |   101K|  2577K|    47   (3)| 00:00:01 |
|   2 |   COUNT             |      |       |       |            |          |
|   3 |    TABLE ACCESS FULL| FOO  |   101K|  1288K|    47   (3)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RN"<=100 AND "RN">=1)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        164  consistent gets
          0  physical reads
          0  redo size
       2504  bytes sent via SQL*Net to client
        590  bytes received via SQL*Net from client
          8  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
        100  rows processed

クエリプランを見ると、述語FOOを適用する前に全表スキャンを実行したことがわかります。rn between 1 and 100そのため、結果セット全体が具体化されました(一貫した取得の数は、おおよそテーブル内のブロックの数です)。

より適切なページ付けクエリを使用した場合(たとえば、 TomKyteがページ付けに関するOracleMagazineの記事を掲載し、askTomでページ付けについてさらに長い議論を行っている場合)、クエリプランSORT ORDER BY STOPKEYに、Oracleが停止できることを認識していることを示す何かが表示されます。ある時点以降の処理。

于 2012-11-27T20:35:15.283 に答える