Por que os índices baseados em funções que eu criei reduzem o custo, mas não aparecem na análise do plano de explicação?


8

Desculpe pelos terríveis nomes de colunas / tabelas, mas como esse é um projeto de trabalho, eu queria garantir que não havia problema em perguntar. Eu estava apenas esperando pelo menos aprender por que não estou vendo meus índices funcionais sendo usados, então me senti melhor em adicionar esses índices em um ambiente de produção.

A consulta está usando uma exibição que eu criei que possui várias colunas diferentes com uma cláusula where que faz o seguinte:

  ....
  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
  ...

Entendo que o Oracle não poderá usar índices se você passar a coluna por uma função e, em vez disso, precisar criar índices baseados em funções. Portanto, antes de criar os índices, obtenho o seguinte custo no meu plano de explicação:

Valor do hash do plano: 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)))

Depois de criar os seguintes índices:

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));

Eu recebo o seguinte plano:

Valor do hash do plano: 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")

Como você pode ver, o custo é bastante reduzido, mas por que não vejo os índices recém-criados?

Eu esperava vê-los usados ​​no plano de explicação, mas, em vez disso, eu o vejo usando o índice de chave primária apropriado e o índice "IDX_ITM".

Entre em contato se precisar de mais informações e vou ver se posso fornecê-las.


11
Você ainda recebe o "novo" plano se soltar os índices? Você recalculou alguma estatística?
Mat

Ele volta ao plano antigo se eu os largar e o novo plano será exibido se eu os adicionar novamente. Ele fez isso de forma consistente em várias tentativas para descobrir o que está acontecendo. Eu usei o OEM para coletar estatísticas depois de soltar os índices e depois de adicioná-los novamente. Também verifiquei o plano de execução que o OEM mostra depois de executar a consulta e ainda mostra o custo reduzido, mas nenhum sinal dos meus novos índices.
Rapida 26/03

Você encontrou o motivo? @Rapida
Vimal Bhaskar

Respostas:


1

Na seção Notas sobre índices baseados em funções da documentação do usuário para CREATE INDEX:

  • Quando você consulta posteriormente uma tabela que usa um índice baseado em função, o Oracle Database não utilizará o índice, a menos que a consulta filtre nulos . No entanto, o Oracle Database utilizará um índice baseado em funções em uma consulta, mesmo que as colunas especificadas na cláusula WHERE estejam em uma ordem diferente da ordem na expressão_coluna que definiu o índice baseado em funções.

Portanto, você pode tentar adicionar NOT NULLcondições apropriadas à sua consulta.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.