Leitura de índices B-Tree: Alteração do Clustering Factor – Parte 2 (Reverse Key Index) | Luís Marques
Leitura de índices B-Tree: Alteração do Clustering Factor – Parte 2 (Reverse Key Index)
Posted on November 19, 2011 by lcmarques
Tinha mostrado anteriormente que apenas reorganizando a tabela seria possível alterar o valor do CF e que uma reorganização do índice nada poderia fazer, pois o CF depende directamente da desordem dos blocos na tabela comparada com a organização no índice. No entanto existe uma forma relativamente simples de alterar o valor do CF que é usando reverse key index (não sei o termo em português).
Existem alguns casos onde este tipo de índices é útil, que foram desenhados essencialmente para resolver o problema de contenção nos blocos (index block contention). Basicamente ocorrem em cenários de muita concorrência (DML insert, update ou delete) onde as várias sessões concorrentes precisam de aceder ao mesmo bloco (chamado "hot block") gerando assim contenção ao nível do bloco do índice causando inumeros wait events do tipo "buffer busy waits", por exemplo.
Mas o post não é sobre os Reverse Key Index, mas sim sobre o CF e como este valor pode ser alterado usando um índice reverted. A alteração da ordem no índice leva a que a desordem na tabela seja diferente. Como exemplo simples, se um ID para inserir na tabela for gerado como 112233 será inserido como 332211 no índice. Este tipo de "reverse" permite que os inserts sejam espalhados por toda a estrutura do índice, evitando a contenção em apenas um só leaf bloco (o mais há direita). Com isto fazemos com que as entradas no índice deixem de estar ordenadas da forma natural e como conhecemos, ou seja, o 112234 a seguir ao 112233.
Apesar de parecer resolver alguns problemas nomeadamente em ambientes RAC muito concorridos, cria uma outra panóplia de problemas que não discutiremos neste post.
O código seguinte mostrará uma tabela, um índice normal que depois será convertido para "reverse" e os respectivos
valores do CF após cada etapa:
SQL> create table t_cf2 as select ceil(dbms_random.value(0,100000)) N1 from dual connect by level <= 100000;
SQL> create index i_cf2 on t_cf2(N1);
SQL> exec dbms_stats.gather_table_stats(null,'T_CF2', cascade=>TRUE);
SQL>  select blevel, leaf_blocks, clustering_factor  from user_indexes where index_name = 'I_CF2';
1         222             99270
SQL> alter index i_cf2 rebuild reverse;
1         222             99265
Temos uma valor diferente no CF, sendo que a diferença é pouca o que significa que o meu exemplo aqui não foi o melhor, no entanto, como nota final não devem de forma alguma usar os RKI sem cuidado, pois a ordem das chaves deixa de ser a natural e os "range scans" deixam de ser possíveis (predicados como BETWEEN, LIKE, > <) e o CBO vai por completo ignorar este tipo de índices. Estes dois posts sobre o CF foram apenas para fazer entender como o CF varia em função das várias ordens seja na tabela ou no índice.