Olá a todos. Nesta quarta parte da série falarei um pouco sobre otimização de índices fornecendo algumas dicas e conceitos sobre esse que é uma das peças mais importantes de uma base de dados Oracle.
1) DICAS GERAIS PARA UM BOM USO DE ÍNDICES
* Criar índices em tabelas que quando consultadas, retornam de 5% a 10% do total de linhas da tabela, ou seja, se há uma tabela de 1000 linhas, e as consultas em cima dessa tabela retornam no máximo 100 linhas, essa coluna usada como filtro é uma candidata a criação de um índice. Índices não tornam a query mais eficiente se esta vai retornar a maioria dos dados da tabela. Neste caso é mais eficiênte um Full Table Scan do que uma busca indexada.
* Criar índices B-Tree em colunas com boa seletividade. A seletividade é o percentual de linhas em uma coluna que possuem o mesmo valor (valor repetido). Uma coluna com seletividade de 5% (densidade de 0.5) é uma coluna com boa seletividade, pois apenas 5% dos valores dessa coluna são valores repetidos. Para colunas com baixa seletividade, recomenda-se criar índices BITMAP, mas isto não é uma regra geral.
* Recomenda-se, quando possível, não indexar colunas que sofrem muitas operações DML, pois nesse caso, tanto os dados nos índices quando nas tabelas devem ser modificados, gerando mais UNDO e REDO.
* Criar índices explicitamente em colunas que possuam Foreign Keys. Criar o índice na coluna que referencia (tabela-filha) e não na referenciada (tabela-pai).
* É mais eficiente criar um índice de várias colunas (Índice Composto) do que um índice para cada coluna usada, pois isso pode aumentar a seletividade do índice composto. Por exemplo:
– Tendo como base a query acima, para otimiza-la, seria melhor criar um índice composto das colunas “last_name” e “first_name” do que um índice para “last_name” e um índice para “first_name”, pois geralmente toda a informação necessária está contida nos blocos do índice. Isso evitaria que a tabela fosse acessada.
* Criar índices com a opção COMPRESS. Caso as colunas indexadas apresentem uma grande quantidade de dados repetidos, pode-se criar indices com taxas de compressão, diminuindo o número de blocos acessados e melhorando a performance geral, mas possívelmente pode prejudicar operações DML (para ter certeza, só testando!!!). É útil em índices compostos onde uma ou mais colunas que fazem parte do índice apresentam um alto grau de repetição de seus valores. Sua sintaxe é:
OBS1: O N indica o grau de compressão
* Pode-se maximizar a criação de índices em grandes tabelas, desabilitando a geração de REDO, criando-os com a clausula NOLOGGING. Ex:
OBS1: REDO não é gerado, impossibilitando e recuperação do índice no caso de uma falha da mídia logo após a criação deste. Caso o índice seja crítico para o negócio, recomenda-se gerar um backup após a criação daquele.
2) VERIFICANDO SE UMA COLUNA É UMA BOA CANDIDATA A RECEBER UM ÍNDICE
* Pode-se usar a query abaixo para ajudar a determinar as colunas candidatas a um índice:
* A query acima possui 2 informações úteis:
– NUM_DISTINCT: Indica o numero de valores distintos em uma coluna. Caso o valor dessa coluna seja muito baixo,por exemplo 3, em relação ao seu total de registros, isso quer dizer que essa coluna possui uma seletividade baixa, tornando-a uma fraca candidata para a criacao de um indice. Caso uma coluna possua uma quantidade alta de valores distintos, em relação ao seu total de registros, como por exemplo 1.000.000, isso torna essa coluna uma forte candidata a criacao de um indice.
– NUM_NULL: Indica o numero de valores nulos para determinada coluna. Se uma coluna possui poucos valores NULL, ela é uma boa candidata a criacao de um indice.
* Segue um resuminho sobre o que foi abordado acima:
– Se a coluna possui uma quantidade elevada de valores distintos E se for usada como predicado (WHERE coluna) e se apenas algumas linhas da tabela (<=10%) forem retornadas, então essa coluna é uma boa candidata.
– Se a coluna não for usada como predicado (WHERE coluna …) E/OU um grande número de linhas foram retornados, então essa coluna não é uma boa candidata a receber um índice
OBS1: Colunas usadas em condições de JOIN tem as mesmas caracteristicas que predicados, portanto o que cabe a um predicado, cabe a uma coluna usada em JOIN, para a criação ou não de indices.
3) CHECANDO SE UM ÍNDICE PRECISA SER RECONSTRUÍDO
* Esse é um assunto que gera muita polêmica, pois uns dizem que o REBUILD é desnecessário nas releases mais atuais, outros dizem que um REBUILD faz milagres, e outros chegam até a automatizar o REBUILD dos índices mais críticos em intervalos regulares de tempo. Eu, particularmente, já vi resultados muito bons em REBUILDs de índices, mas não em todos os casos. As vezes, a operação de REBUILD pode ser muito traumática.
* Para ajudar a verificar se um índice precisa ser reconstruído:
3.1) Analisar o indice
3.2) Executar a seguinte query:
OBS1: Caso o valor de DEL_LF_ROWS/LF_ROWS seja maior que 2, ou LF_ROWS seja menor que LF_BLKS, ou HEIGHT seja 4, então o índice deveria ser reconstruído.
OBS2: Recomenda-se realizar o rebuild e computar as estatísticas na mesma operação. Ex:
Por enquanto é isso meus caros DBAs/desenvolvedores/curiosos… até a próxima.
Keep Tuning!
Fabricio, muito bom o artigo. Só gostaria de acrescentar algumas informações:
1- Documentações oficiais da Oracle informam que índices b-tree são eficientes quando a consulta retorna até 4% dos dados da(s) tabela(s), porém na prática, observa-se que o percentual pode ser maior. Vc afirmou entre 5% e 10%, mas já vi autores afirmarem valores até mesmo até 15% e 20%. Não há um consenso sobre o valor exato e nem há como calcular este valor exato (as variantes são complexas), o importante é ter um valor como referência para criá-lo e sempre testar a eficiência do índice após a sua criação;
2- Para mais detalhes sobre índices bitmap indico o artigo: http://www.fabioprado.net/2011/07/otimizando-consultas-com-indices-bitmap.html
3- Sobre a compressão de índices, talvez seja necessário o licenciamento da option Advanced Compression para usar este recurso. Já pesquisei anteriormente sobre isso e ainda não encontrei uma resposta exata. Vc saberia me informar?
4- Quanto ao rebuild index, a nota com ID 122008.1 do MOS é bem clara sobre quando um índice b-tree deve ser reconstruído. Ela informa que deve-se reconstruí-los quando o nível (blevel) for maior que 4 e/ou quando a quantidade de linhas deletadas for maior que 20% do total de linhas da tabela.
[]s
Olá Fabio, obrigado pelo seu comentário.
É aquele negócio: Testar, testar e testar… no meu ambiente10% pode ser uma maravilha mas em outro lugar, não serviria pra nada. O importante é fazer funcionar da forma que agrade a todos.
Com relação a compressão de índices, ela requer sim a licença “Advanced Compression Option (ACO)”.
Já com relação a quantidade de linhas deletadas antes de se executar um rebuild, eu penso da seguinte forma: Se essas linhas deletadas serão novamente inseridas nessa tabela, em um curto período de tempo, então creio que o REBUILD não seja necessário, pois o espaço préviamente alocado será reaproveitado, você não concorda? Agora se essas linhas forem permanentemente removidas da tabela, ai sim o REBUILD seria uma opção considerável. Depedendo do tamanho do índice, essa operação pode ser bem complicada, mesmo usando a opção ONLINE.
Mais uma vez obrigado pelo comentário.
Fabrício, o rebuild é necessário sim após apagar dados. A estrutura dos índices não é igual a das tabelas, ou seja, os blocos dos índices NUNCA SERÃO REUTILIZADOS.
E obrigado pela informação da option!
[]s
Se for utilizado o BASIC COMPRESSION, ou seja, na sintaxe ser colocado apenas “CREATE INDEX nome_indice ON tabela(colunas[…]) CONPRESS” , não é necessário ter a option do Advanced Compress.
Se a tabela for volátil, sofrer bastante manipulações de dados pontuais, a compressão terá que ser feita de tempos em tempos nos índices compostos, pois o BASIC COMPRESSION, comprime somente a situação do momento, as novas folhas ficarão de fora.
Só uma retificação: Index Conpression não requer a licença Advanced Compression. O que requer essa licença e a compressão OLTP.
Peço desculpas pela informação incorreta.
Fala Fabrício, muito bom o artigo, faltou falar um pouco mais sobre índice bitmap, rebuild online, mas ta valendo.
Abraço meu amigo.
Parabens Fabricio pelo artigo.
Hoje entrei de novo neste artigo e quero fazer uma correcao referente ao meu ultimo comentario. Eu havia dito que os blocos de linhas apagadas nos indices nunca seriam reutilizados, mas na verdade eles podem sim ser reutilizados em uma unica situacao: qdo o mesmo valor q foi apagado é reinserido, ou seja, se existe um valor FABIO PRADO na coluna NM_CLIENTE (com indice btree) e uma linha da tabela CLIENTE que foi apagado e novamente reinserido, ele podera ocupar o mesmo bloco q ficou vazio no indice, se ele ainda nao sofreu um rebuild.
Abs
Fabio, vc disse:
* Criar índices B-Tree em colunas com boa seletividade. A seletividade é o percentual de linhas em uma coluna que possuem o mesmo valor (valor repetido). Uma coluna com seletividade de 5% (densidade de 0.5) é uma coluna com boa seletividade, pois apenas 5% dos valores dessa coluna são valores repetidos. Para colunas com baixa seletividade, recomenda-se criar índices BITMAP, mas isto não é uma regra geral.
* Índices bitmap são recomendados em colunas de baixa “cardinalidade”
Você usa a palavra seletividade , mas eu acho que o mais adequado seria cardinalidade não?
Ja a seletividade seria a cardinalidade/numero de linhas * 100% que nos mostra se o índice é eficiente é necessário. Baixa seletividade gera mais i/o tornando o índice ineficiente.
Olá Mario! Quem escreveu o artigo foi o Fabricio, mas vou tentar responder…
O Fabricio escreveu da forma correta, acredito que vc não interpretou da maneira como deveria.
Ele usou os dois termos – seletividade e cardinalidade.
Boa seletividade significa seletividade BAIXA. Quanto mais baixa, melhor para o índice B-tree.
Cardinalidade é a quantidade de valores diferentes para aquele domínio.
Quando a cardinalidade é baixa recomenda-se índices BITMAP (e não B-tree).
Portanto está correto!
Acredito que quando ele disse “baixa seletividade” é porque a porcentagem é alta, e aí não vale a pena usar indice B-tree.
Talvez vc tenha confundido essa “baixa seletividade” com “baixa porcentagem”, que são coisas opostas!
Excelente post!
Me ajudou bastante.
Alex
http://www.alexbarbosa.info