web-dev-qa-db-ja.com

作成した機能ベースのインデックスはコストを下げたが、説明プランの内訳に表示されないのはなぜですか?

ひどい列/テーブル名で申し訳ありませんが、これは作業プロジェクト用なので、質問しても問題ないことを保証したいと思いました。少なくとも機能インデックスが使用されていない理由を少なくとも知りたいと思っていたので、本番環境にこのインデックスを追加した方がよいと感じました。

クエリは、次のことを行うwhere句を含むさまざまな列を含む、私が作成したビューを使用しています。

  ....
  AND e.sysid = NVL(wi.ALPHAid, -999)
  AND NVL(wi.ALPHAid,   -999)       <> -999
  AND NVL(wi.BRAVOid,   -999)        = -999
  AND NVL(wi.CHARLIEid, -999)        = -999
  ...

関数を介して列を渡し、代わりに関数ベースのインデックスを作成する必要がある場合、Oracleはインデックスを使用できないことは私の理解です。したがって、インデックスを作成する前に、説明プランで次のコストを取得します。

計画ハッシュ値:1233409744

-------------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name                           | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |                                |     1 |   223 |    56   (6)| 00:00:01 |
|   1 |  SORT ORDER BY                   |                                |     1 |   223 |    56   (6)| 00:00:01 |
|   2 |   HASH UNIQUE                    |                                |     1 |   223 |    55   (4)| 00:00:01 |
|   3 |    NESTED LOOPS                  |                                |     1 |   223 |    54   (2)| 00:00:01 |
|   4 |     NESTED LOOPS                 |                                |     1 |   136 |    49   (3)| 00:00:01 |
|   5 |      NESTED LOOPS OUTER          |                                |     1 |   112 |    48   (3)| 00:00:01 |
|*  6 |       HASH JOIN                  |                                |     1 |    87 |    48   (3)| 00:00:01 |
|*  7 |        HASH JOIN                 |                                |  3261 | 97830 |    29   (4)| 00:00:01 |
|   8 |         TABLE ACCESS FULL        | CHARLIE                        |  3261 | 39132 |    15   (0)| 00:00:01 |
|   9 |         TABLE ACCESS FULL        | BRAVO                          |  3261 | 58698 |    13   (0)| 00:00:01 |
|* 10 |        TABLE ACCESS FULL         | ALPHA                          |  3291 |   183K|    19   (0)| 00:00:01 |
|  11 |       TABLE ACCESS BY INDEX ROWID| LOCATION                       |     1 |    25 |     0   (0)| 00:00:01 |
|* 12 |        INDEX RANGE SCAN          | ALPHA_SRVDELLOC_IN1            |     1 |       |     0   (0)| 00:00:01 |
|  13 |      TABLE ACCESS BY INDEX ROWID | DELTA                          |     1 |    24 |     1   (0)| 00:00:01 |
|* 14 |       INDEX UNIQUE SCAN          | DELTA_PK                       |     1 |       |     0   (0)| 00:00:01 |
|* 15 |     TABLE ACCESS BY INDEX ROWID  | ITEM                           |     1 |    87 |     5   (0)| 00:00:01 |
|* 16 |      INDEX SKIP SCAN             | IDX_ITM                        |     1 |       |     4   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------------

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

   6 - access("PR"."SYSID"="E"."BRAVOID" AND "E"."CHARLIEID"="MR"."SYSID")
   7 - access("PR"."SYSID"="MR"."BRAVOID")
  10 - filter("E"."SYSID"<>(-999))
  12 - access("E"."SYSID"="SD"."ALPHAID"(+))
       filter("SD"."ALPHAID"(+)<>(-999))
  14 - access("PR"."DELTAID"="P"."SYSID")
  15 - filter(("WI"."TYPE"='XZ' OR "WI"."TYPE"='Z' OR 
              "WI"."TYPE"='X') AND "WI"."DELINQUENT"='F' AND ("WI"."ACTIVE"='F' OR 
              NVL("WI"."LOCKEDBY",(-999))<>(-999)) AND "WI"."SUSPENDED"='F' AND ("WI"."LOCKEDBY" 
              IS NULL OR "WI"."LOCKEDBY"=12))
  16 - access("WI"."CODE"='MISSING' AND "WI"."TERMINATED"='F')
       filter("WI"."TERMINATED"='F' AND NVL("WI"."ALPHAID",(-999))<>(-999) AND 
              NVL("WI"."BRAVOID",(-999))=(-999) AND NVL("WI"."CHARLIEID",(-999))=(-999) AND 
              "E"."SYSID"=NVL("WI"."ALPHAID",(-999)))

以下のインデックスを作成した後:

CREATE INDEX "IDX_WFITEM_NVL_BRAVOID" ON ITEM (NVL(BRAVOID, -999));
CREATE INDEX "IDX_WFITEM_NVL_CHARLIEID" ON ITEM (NVL(CHARLIEID, -999));
CREATE INDEX "IDX_WFITEM_NVL_ALPHAID" ON ITEM (NVL(ALPHAID, -999));

私は次の計画を得ます:

計画ハッシュ値:1066773928

----------------------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name                           | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                                |     1 |   232 |    12  (17)| 00:00:01 |
|   1 |  SORT ORDER BY                      |                                |     1 |   232 |    12  (17)| 00:00:01 |
|   2 |   HASH UNIQUE                       |                                |     1 |   232 |    11  (10)| 00:00:01 |
|   3 |    NESTED LOOPS                     |                                |       |       |            |          |
|   4 |     NESTED LOOPS                    |                                |     1 |   232 |    10   (0)| 00:00:01 |
|   5 |      NESTED LOOPS                   |                                |     1 |   208 |     9   (0)| 00:00:01 |
|   6 |       NESTED LOOPS                  |                                |     1 |   190 |     8   (0)| 00:00:01 |
|   7 |        NESTED LOOPS OUTER           |                                |     1 |   178 |     7   (0)| 00:00:01 |
|   8 |         NESTED LOOPS                |                                |     1 |   153 |     7   (0)| 00:00:01 |
|*  9 |          TABLE ACCESS BY INDEX ROWID| ITEM                           |     1 |    96 |     6   (0)| 00:00:01 |
|* 10 |           INDEX SKIP SCAN           | IDX_ITM                        |     1 |       |     5   (0)| 00:00:01 |
|  11 |          TABLE ACCESS BY INDEX ROWID| ALPHA                          |     1 |    57 |     1   (0)| 00:00:01 |
|* 12 |           INDEX UNIQUE SCAN         | ALPHA_PK                       |     1 |       |     0   (0)| 00:00:01 |
|  13 |         TABLE ACCESS BY INDEX ROWID | LOCATION                       |     1 |    25 |     0   (0)| 00:00:01 |
|* 14 |          INDEX RANGE SCAN           | ALPHA_SRVDELLOC_IN1            |     1 |       |     0   (0)| 00:00:01 |
|  15 |        TABLE ACCESS BY INDEX ROWID  | CHARLIE                        |     1 |    12 |     1   (0)| 00:00:01 |
|* 16 |         INDEX UNIQUE SCAN           | CHARLIE_PK                     |     1 |       |     0   (0)| 00:00:01 |
|  17 |       TABLE ACCESS BY INDEX ROWID   | BRAVO                          |     1 |    18 |     1   (0)| 00:00:01 |
|* 18 |        INDEX UNIQUE SCAN            | BRAVO_PK                       |     1 |       |     0   (0)| 00:00:01 |
|* 19 |      INDEX UNIQUE SCAN              | DELTA_PK                       |     1 |       |     0   (0)| 00:00:01 |
|  20 |     TABLE ACCESS BY INDEX ROWID     | DELTA                          |     1 |    24 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------------

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

   9 - filter(("WI"."TYPE"='XZ' OR "WI"."TYPE"='Z' OR 
              "WI"."TYPE"='X') AND "WI"."DELINQUENT"='F' AND ("WI"."ACTIVE"='F' OR 
              NVL("WI"."LOCKEDBY",(-999))<>(-999)) AND "WI"."SUSPENDED"='F' AND ("WI"."LOCKEDBY" IS 
              NULL OR "WI"."LOCKEDBY"=12))
  10 - access("WI"."CODE"='MISSING' AND "WI"."TERMINATED"='F')
       filter("WI"."TERMINATED"='F' AND NVL("BRAVOID",(-999))=(-999) AND 
              NVL("CHARLIEID",(-999))=(-999) AND NVL("ALPHAID",(-999))<>(-999))
  12 - access("E"."SYSID"=NVL("ALPHAID",(-999)))
       filter("E"."SYSID"<>(-999))
  14 - access("E"."SYSID"="SD"."ALPHAID"(+))
       filter("SD"."ALPHAID"(+)<>(-999))
  16 - access("E"."CHARLIEID"="MR"."SYSID")
  18 - access("PR"."SYSID"="MR"."BRAVOID")
       filter("PR"."SYSID"="E"."BRAVOID")
  19 - access("PR"."DELTAID"="P"."SYSID")

ご覧のとおり、コストは大幅に削減されていますが、新しく作成されたインデックスが表示されないのはなぜですか?

それらが説明プランで使用されることを期待していましたが、代わりに適切な主キーインデックスと「IDX_ITM」インデックスを使用してそれを確認しました。

さらに情報が必要な場合はお知らせください。提供できるかどうか確認します。

8
Rapida

CREATE INDEXのユーザードキュメントの 関数ベースのインデックスに関する注意 セクションから:

  • その後、関数ベースのインデックスを使用するテーブルをクエリすると、Oracleデータベースは、クエリがnullを除外しない限り、インデックスを使用しません。ただし、WHERE句で指定された列の順序が関数ベースの索引を定義したcolumn_expressionの順序と異なる場合でも、Oracle Databaseは問合せで関数ベースの索引を使用します。

したがって、適切なNOT NULL条件をクエリに追加してみてください。

1
Sentinel