-1
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2822030489
---------------------------------------------------------------------------------------------

| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |     1 |    46 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| PURCHASE      |     1 |    46 |     2   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | PK_PURCHASENO |     1 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("PURCHASENO"=9989)

14 rows selected.

誰かが私にこれが何を意味するのか説明できますか?

Oracle がこのクエリを実行するためにインデックスを使用しているということですか?

4

1 に答える 1

1

ヒントは計画にあります。

これは、インデックス PK_PURCHASENO を一意にスキャンしていることを意味します。

| Operation         | Name          | Rows  |
---------------------------------------------
| INDEX UNIQUE SCAN | PK_PURCHASENO |     1 |

これがあなたの主キーであり、クエリから判断すると、それは PURCHASENO 列にあると名前で想定しています。主キーは一意である必要があるため、これはそれほど驚くことではありません。の列は、1 つの行のみを返していることを示していることに注意してください。これはこれを裏付けています。

もう一つ重要なことは、この行です。

| Id  | Operation                   | Name          | Rows  | Bytes |
---------------------------------------------------------------------
|   1 |  TABLE ACCESS BY INDEX ROWID| PURCHASE      |     1 |    46 |

インデックスを一意にスキャンしましたが、インデックスからデータを選択するだけでなく、書いたようにテーブルからデータを返す必要もありますselect *。ROWID は、行を識別するテーブル内の一意のアドレスです。ROWID を使用して (単一の) 行にアクセスするのが、データを返す最速の方法です。Oracle は、主キー インデックスで必要な行を見つけ、行 ID を使用して残りの行を選択します。バイト列が 46 であることがわかります。これは、行の長さが 46 バイトであることを意味します。

代わりに、次のクエリを使用すると、ROWID によるアクセスは不要になります。

select purchaseno
  from purchase
 where purchaseno = 1000

これは、列 PURCHASENO が既に索引にあるためです。テーブルにアクセスする必要はありません。select *このため、「有害」と見なされます。ディスクから読み取る必要があるデータの量と、ネットワーク経由で送信する必要があるデータの量が増える可能性があるだけでなく、追加の操作が必要になる可能性があることも意味しますあなたのデータにアクセスするため。必要な行のみを選択してください。

最後の 2 つのポイントは、数値であるにもかかわらず、クエリで値 PUCRHASENO が引用符で囲まれていることです。PURCHASENO が実際には文字である場合、これは問題ありませんが、数字の場合は、文字を暗黙的に数字に変換しているため、ここで何かを危険にさらしています。Oracleでは、次の理由により、暗黙的な変換を明示的に推奨していません。

  • 明示的なデータ型変換関数を使用すると、SQL ステートメントが理解しやすくなります。

  • 暗黙的なデータ型変換は、特に列値のデータ型が定数のデータ型に変換される場合、逆ではなく、パフォーマンスに悪影響を与える可能性があります。

  • 暗黙的な変換は、それが発生するコンテキストに依存し、すべての場合で同じように機能するとは限りません。たとえば、日時値から VARCHAR2 値への暗黙的な変換では、 NLS_DATE_FORMAT パラメータの値によっては予期しない年が返される場合があります。

  • 暗黙的な変換のアルゴリズムは、ソフトウェア リリース間および Oracle 製品間で変更される可能性があります。明示的な変換の動作はより予測可能です。

これを行うと、インデックスを使用しないほどオプティマイザー混乱する可能性がありますが、これはあなたのような単純なクエリでは起こりそうにありません。

最後に、これは個人的な好みですが、PURCHASE テーブルの主キーの名前はかなり紛らわしいと思います。テーブルが主キーを 1 つしか持つことができず、その名前のオブジェクトが 1 つのスキーマ内に 1 つしか存在できないとPK_<table name>いうよりも、より良い標準です。PK_<column name>ただし、主キーとして同じ列名を持つ 2 つのテーブルを持つことは可能です。

『Oracle Performance Tuning Guide』には、Explain Plan を読んで理解するための章があり、読むことを強くお勧めします。

于 2013-05-18T11:18:48.717 に答える