A partir da versão do Oracle 11g, é possível criar e alterar os índices para INVISIBLE/VISIBLE.
Ao alterar um índice para invisible, por default o otimizador do Oracle não utiliza o mesmo para montar um plano de execução. A menos, que o parâmetro optimizer_use_invisible_indexes (default FALSE) esteja definido como TRUE a nível de instância ou de sessão. Neste último, o índice também será usado apenas a nível de sessão.
Com esta feature, é possível realizar a criação de um índice invisible em produção sem afetar os planos de execução existentes. Essa possibilidade é bastante útil quando, por exemplo, não temos um ambiente de testes e precisamos validar o impacto da criação do índice direto no ambiente de produção.
Abaixo vou exemplificar o uso desta feature:
Primeiramente iremos criar e popular uma tabela e realizar a criação do índice invisible, para que possamos realizar os testes com o uso da feature invisible index.
Primeiramente iremos criar e popular uma tabela e realizar a criação do índice invisible, para que possamos realizar os testes com o uso da feature invisible index.
SQL> conn lamim/lamim SQL> create table tst_invisible_ix ( Connected. SQL> numero number ); SQL> BEGIN 2 3 Table created. INSERT INTO tst_invisible_ix VALUES (i); FOR i IN 1 .. 10000 LOOP END LOOP; COMMIT; PL/SQL procedure successfully completed. END; / 2 3 4 5 6 7 SQL> SQL> SQL>
Antes de efetivamente realizar os testes, irei realizar uma coleta de estatística da tabela recém criada.
SQL> EXEC DBMS_STATS.gather_table_stats(USER, 'tst_invisible_ix', cascade=> TRUE); PL/SQL procedure successfully completed.Agora vamos validar o comportamento do plano de execução com e sem um índice em modo invisible.
SQL> show parameter invisible; NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ optimizer_use_invisible_indexes boolean FALSE SQL> select * from tst_invisible_ix where numero=123; NUMERO ---------- 123 Execution Plan ---------------------------------------------------------- Plan hash value: 978504830 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 4 | 6 (0)| 00:00:01 | |* 1 | TABLE ACCESS FULL| TST_INVISIBLE_IX | 1 | 4 | 6 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("NUMERO"=123) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 23 consistent gets 0 physical reads 0 redo size 525 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed SQL>
No exemplo acima é possível perceber que a consulta realiza um acesso full a tabela e não utiliza o índice criado com o invisible. Para testarmos a utilização do índice, podemos usar um hint na query ou alterar o parâmetro optimizer_use_invisible_indexes a nível de sessão, evitando assim que o índice impacte em outros processos e/ou aplicações.
SQL> select * from tst_invisible_ix where numero=123; NUMERO ---------- 123 Execution Plan ---------------------------------------------------------- Plan hash value: 1674343203 ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 4 | 1 (0)| 00:00:01 | |* 1 | INDEX RANGE SCAN| IX_TST_INVISIBLE_IX01 | 1 | 4 | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("NUMERO"=123) Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 3 consistent gets 0 physical reads 0 redo size 525 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
Podemos notar que após a alteração do parâmetro a consulta não realiza mais um acesso full e passa a utilizar o índice. Lembrando que o uso do índice ocorre apenas na sessão atual, devido a alteração do parâmetro optimizer_use_invisible_indexes.
Para tornar o índice visível para todo o banco, basta executar o comando alter index index_name visible, da mesma forma se desejarmos alterar um índice já criado para invisivel, basta executar um alter index_name inivisible.
SQL> conn lamim/lamim Connected. SQL> alter index LAMIM.IX_TST_INVISIBLE_IX01 visible; Index altered. SQL> set autotrace on SQL> select * from lamim.tst_invisible_ix where numero=123; NUMERO ---------- 123 Execution Plan ---------------------------------------------------------- Plan hash value: 1674343203 ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 4 | 1 (0)| 00:00:01 | |* 1 | INDEX RANGE SCAN| IX_TST_INVISIBLE_IX01 | 1 | 4 | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("NUMERO"=123) Statistics ---------------------------------------------------------- 24 recursive calls 0 db block gets 35 consistent gets 0 physical reads 0 redo size 525 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 6 sorts (memory) 0 sorts (disk) 1 rows processedAfim de validar se um índice está visivel ou invisível, podemos consultar a coluna visibility da dba/user_indexes.
SQL> select index_name, visibility from dba_indexes where index_name='IX_TST_INVISIBLE_IX01'; INDEX_NAME VISIBILIT ------------------------------ --------- IX_TST_INVISIBLE_IX01 VISIBLE
Fonte:https://docs.oracle.com/cd/B28359_01/server.111/b28310/indexes004.htm
http://www.orafaq.com/wiki/Invisible_indexes
Comentários
Postar um comentário