0

約 50 列のテーブルに約 800 万のレコードがあり、いくつかのレコードを非常に迅速に表示する必要があるため、この目的のために FIRST_ROWS(10) ヒントを使用し、驚くほど高速に動作します。

SELECT /*+ FIRST_ROWS(10) */ ABC.view_ABC.ID, ABC.view_ABC.VERSION, ABC.view_ABC.M_UUID, ABC.view_ABC.M_PROCESS_NAME FROM ABC.view_ABC

ただし、ORDER BY の節、たとえば creationtime (そのテーブルの各行のほぼ一意の値) を配置すると、このクエリはすべての列を返すのに時間がかかります。

SELECT /*+ FIRST_ROWS(10) */ ABC.view_ABC.ID, ABC.view_ABC.VERSION, ABC.view_ABC.M_UUID, ABC.view_ABC.M_PROCESS_NAME FROM ABC.view_ABC ORDER BY ABC.view_ABC.CREATIONTIME DESC

私が気づいたことの1つは次のとおりです。複数の行に同じ値を持つ VERSION のような列に ORDER BY を配置すると、より良い結果が得られます。

これは、このテーブルORDER BYの列のような一意の列では効率的に機能していません。ID

考慮に値するもう1つのことは次のとおりです。フェッチする列の数を減らすと、たとえば 50 列ではなく 3 列にすると、結果はどういうわけか速くなります。

PS 収集統計はこのテーブルで毎週実行されますが、データは 1 時間ごとにプッシュされます。INSERTこのテーブルではステートメントのみが実行されており、このテーブルではクエリは実行されていDELETEません。UPDATE

また、このテーブルなしで作成された単純なビューがあり、上記のクエリは同じビューで実行されています。

4

2 に答える 2

0

この列には複数列のインデックスがあります ( CREATION_TIME)。何らかの理由で、オラクル ヒント オプティマイザーがこのインデックスを使用していませんでした。

ただし、同じテーブルに別の列 ( TERMINATION_TIME) があり、それ自体にインデックスがありました。したがって、同じクエリを使用しますが、このインデックス付きの列をORDER BY句に使用します。

以下は、複数列インデックスの一部である ORDER BY 句で CREATION_TIME を使用した最初のクエリの説明プランです。

-------------------------------------------------------------------------------------------------------------
| Id  | Operation          | Name                           | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                                |  7406K|   473M|       |   308K  (1)| 01:01:40 |
|   1 |  SORT ORDER BY     |                                |  7406K|   473M|   567M|   308K  (1)| 01:01:40 |
|   2 |   TABLE ACCESS FULL| Table_ABC                      |  7406K|   473M|       |   189K  (1)| 00:37:57 |
-------------------------------------------------------------------------------------------------------------

そして、これは TERMINATION_TIME を ORDER BY 句として使用しています。

--------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name                           | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                                |    10 |   670 |    10   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TABLE_ABC                      |  7406K|   473M|    10   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN DESCENDING| XGN620150305000000             |    10 |       |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------------

ご覧のとおり、コスト、関連する行数、一時スペースの使用量 (後のケースでは使用されません)、そして最後に時間に明らかな違いがあります。

クエリの応答時間が大幅に改善されました。

ありがとう。

于 2016-08-04T13:18:23.433 に答える
0

句がなければ、order byオプティマイザーは、ビューが隠している結合操作を実行し、データがあればすぐにデータを返し始めることができます。ヒントは、たとえば、マージ結合の代わりにネストされたループ結合を実行するように、基になるテーブルへのアクセス方法を変更しています。これにより、最初に一致する行をすばやく見つけることができます。ただし、すべてのデータを返すには全体的に効率が悪い可能性があります。あなたのヒントは、クエリ全体の速度よりも返される行の最初のバッチの速度を優先することをオプティマイザーに伝えています。

句を追加するorder byと、データを並べ替える前にすべてのデータを見つける必要があります。すべての結合条件が満たされ、ネストされたループ/マージなどがすべて完了する必要があります。その後行が返される前に、結果セット全体を指定した順序で並べ替える必要があります。

注文している列にインデックスが付けられていて、そのインデックスがオプティマイザーによって使用されている (または使用できる) 場合、駆動テーブルの行を識別するために、それを並べ替えに組み込むことができますが、信頼することはできませその上で、オプティマイザーはデータと統計が変化するにつれて計画を変更できるためです。

ヒントの有無にかかわらず、さまざまなクエリの実行計画を調べて、各ケースでオプティマイザが何を行っているかを確認すると便利な場合があります。これには、一連のステップのどこで並べ替え操作を行っているか、および型が含まれます。のジョインをしています。

于 2016-08-01T09:12:05.007 に答える