Quantos índices de banco de dados são muitos?

109

Estou trabalhando em um projeto com um banco de dados Oracle bastante grande (embora minha pergunta se aplique igualmente a outros bancos de dados). Temos uma interface da web que permite aos usuários pesquisar em quase todas as combinações possíveis de campos.

Para tornar essas pesquisas mais rápidas, estamos adicionando índices aos campos e combinações de campos nos quais acreditamos que os usuários irão pesquisar normalmente. No entanto, como não sabemos realmente como nossos clientes usarão este software, é difícil dizer quais índices criar.

O espaço não é uma preocupação; temos uma unidade RAID de 4 terabytes, da qual usamos apenas uma pequena fração. No entanto, estou preocupado com as possíveis penalidades de desempenho por ter muitos índices. Como esses índices precisam ser atualizados sempre que uma linha é adicionada, excluída ou modificada, imagino que não seria uma boa ideia ter dezenas de índices em uma única tabela.

Então, quantos índices são considerados muitos? 10? 25? 50? Ou devo apenas cobrir os casos realmente, realmente comuns e óbvios e ignorar todo o resto?

Eli Courtwright
fonte

Respostas:

87

Depende das operações que ocorrem na mesa.

Se houver muitos SELECTs e muito poucas mudanças, indexe o quanto quiser ... isso (potencialmente) irá acelerar as instruções SELECT.

Se a tabela for fortemente atingida por UPDATEs, INSERTs + DELETEs ... estes serão muito lentos com muitos índices, pois todos eles precisam ser modificados cada vez que uma dessas operações ocorrer

Dito isso, você pode adicionar claramente muitos índices inúteis a uma tabela que não fará nada. Adicionar índices B-Tree a uma coluna com 2 valores distintos não fará sentido, pois não adiciona nada em termos de pesquisa de dados. Quanto mais exclusivos os valores em uma coluna, mais ela se beneficiará de um índice.

cagcowboy
fonte
1
Só para esclarecer, o índice de 2 valores pode não ser inútil em casos específicos, quando um valor acontece raramente e você deseja consultá-lo. Portanto, não se trata de quão únicos os valores são, mas de quão seletivo é o índice.
charlie_pl
44

Eu geralmente procuro assim.

  1. Obtenha um registro das consultas reais executadas nos dados em um dia típico.
  2. Adicione índices para que as consultas mais importantes atinjam os índices em seu plano de execução.
  3. Tente evitar indexar campos que possuem muitas atualizações ou inserções
  4. Após alguns índices, obtenha um novo log e repita.

Como acontece com qualquer otimização, eu paro quando o desempenho solicitado é alcançado (isso obviamente implica que o ponto 0. estaria recebendo requisitos de desempenho específicos).

Sklivvz
fonte
26

Todo mundo tem lhe dado ótimos conselhos. Tenho uma sugestão adicional para você conforme você avança. Em algum momento, você deve tomar uma decisão quanto à sua melhor estratégia de indexação. No final das contas, a melhor estratégia de indexação PLANNED ainda pode acabar criando índices que acabam não sendo usados. Uma estratégia que permite localizar índices que não são usados ​​é monitorar o uso do índice. Você faz isso da seguinte maneira: -

alter index my_index_name monitoring usage;

Você pode então monitorar se o índice é usado ou não daquele ponto em diante, consultando v $ object_usage. Informações sobre isso podem ser encontradas no Oracle® Database Administrator's Guide .

Lembre-se de que, se você tiver uma estratégia de armazenamento de eliminar índices antes de atualizar uma tabela e, em seguida, recriá-los, terá que configurar o índice para monitoramento novamente e perderá todo o histórico de monitoramento desse índice.

Mike McAllister
fonte
14

No armazenamento de dados, é muito comum ter um grande número de índices. Trabalhei com tabelas de fatos com duzentas colunas e 190 delas indexadas.

Embora haja uma sobrecarga para isso, deve ser entendido no contexto que em um data warehouse, geralmente inserimos uma linha apenas uma vez, nunca a atualizamos, mas ela pode participar de milhares de consultas SELECT que podem se beneficiar da indexação em qualquer um dos as colunas.

Para flexibilidade máxima, um data warehouse geralmente usa índices de bitmap de coluna única, exceto em colunas de alta cardinalidade, onde índices btree (compactados) podem ser usados.

A sobrecarga na manutenção do índice está principalmente associada à despesa de gravação em muitos blocos e a divisão do bloco à medida que novas linhas são adicionadas com valores que estão "no meio" dos intervalos de valores existentes para essa coluna. Isso pode ser atenuado pelo particionamento e tendo as novas cargas de dados alinhadas com o esquema de particionamento e usando inserções de caminho direto.

Para abordar sua questão mais diretamente, acho que provavelmente não há problema em indexar o óbvio no início, mas não tenha medo de adicionar mais índices se as consultas na tabela forem se beneficiar.

David Aldridge
fonte
Tantos de fato? Eu teria adivinhado que você estava prestes a dizer dimensão. Esse é um caso de uso bastante bizarro. Mas, você é demais como um DBA, então vou dizer, estou obviamente faltando alguma coisa.
Stephanie Page
@Stephanie, temos praticamente o mesmo cenário. David mencionou que esses são índices de bitmap. Também usamos índices BITMAP JOIN. Sim, em fatos. O Oracle pode fazer operações AND muito eficientes em índices de bitmap. Por exemplo, você poderia ter a cláusula WHERE com 5 atributos de baixa cardinalidade, cada um dos quais com um índice de bitmap. Se você olhar para o plano de execução, ele teria um bitmap E operações (basicamente um bitmap e uma operação eficientes) e, no plano de execução, você verá a conversão de bitmap em rowids. É muito rápido.
Tagar
12

Em uma paráfrase de Einstein sobre simplicidade, adicione quantos índices precisar e nada mais.

Sério, entretanto, cada índice que você adiciona requer manutenção sempre que os dados são adicionados à tabela. Em tabelas que são principalmente somente leitura, muitos índices são uma coisa boa. Em mesas altamente dinâmicas, quanto menos, melhor.

Meu conselho é cobrir os casos comuns e óbvios e, então, conforme você encontrar problemas em que precisa de mais velocidade para obter dados de tabelas específicas, avalie e adicione índices nesse ponto.

Além disso, é uma boa ideia reavaliar seus esquemas de indexação a cada poucos meses, apenas para ver se há algo novo que precisa de indexação ou algum índice que você criou que não está sendo usado para nada e deve ser eliminado .

Josef
fonte
1
Eu concordo com a reavaliação. A boa administração nunca é uma tarefa do tipo "configure e esqueça". Mudanças de software. Mudança de requisitos. Alterações de uso. Uma funcionalidade nova e aparentemente trivial introduzida um dia pode rapidamente se tornar seu maior gargalo, e o código básico de ontem pode se tornar dormente e gordura desnecessária que meramente fica por aí consumindo recursos. Também concordo com uma abordagem iterativa. Se você fizer muito de uma vez, não saberá o que funcionou.
durette
6

Além dos pontos que todos levantaram, o Cost Based Optimizer incorre em um custo ao criar um plano para uma instrução SQL se houver mais índices porque há mais combinações a serem consideradas. Você pode reduzir isso usando variáveis ​​de ligação corretamente para que as instruções SQL permaneçam no cache SQL. O Oracle pode então fazer uma análise suave e reutilizar o plano que encontrou da última vez.

Como sempre, nada é simples. Se houver colunas distorcidas e histogramas envolvidos, isso pode ser uma má ideia.

Em nossos aplicativos da web, tendemos a limitar as combinações de pesquisas que permitimos. Caso contrário, você teria que testar literalmente todas as combinações de desempenho para garantir que não tivesse um problema oculto que alguém encontrasse um dia. Também implementamos limites de recursos para impedir que isso cause problemas em outras partes do aplicativo, caso algo dê errado.

WW.
fonte
Votei, mas ... Eu diria que o tempo extra de análise, embora seja interessante e acadêmico, nunca influenciaria minha escolha pelo número correto de índices. aceita?
Stephanie Page
@StephaniePage Eu não fiz um experimento para provar nada. No entanto, vi um projeto que ingenuamente criou um índice de coluna única em cada coluna. Se algumas tabelas tiverem 80 colunas, acho que pode começar a ter um impacto. A Oracle parece considerar o custo de acesso de cada índice. Mas sim, concordo, há coisas mais importantes a considerar do que isso.
WW.
Mmm ... Eu acredito que há um tempo máximo que o Oracle gastará em uma análise difícil ... considere um SQL com mais do que algumas tabelas, digamos 7 ou 8, a escolha da ordem de junção sozinha poderia gerar centenas de possíveis caminhos de acesso.
Stephanie Page
6

Fiz alguns testes simples no meu projeto real e no banco de dados MySql real. Já respondi neste tópico: Qual é o custo de indexar várias colunas db?

Mas acho que será melhor se eu citar aqui:

Fiz alguns testes simples usando meu projeto real e banco de dados MySql real.

Meus resultados são: adicionar índice médio (1-3 colunas em um índice) a uma tabela - torna as inserções mais lentas em 2,1%. Portanto, se você adicionar 20 índices, suas inserções serão mais lentas em 40-50%. Mas suas seleções serão 10-100 vezes mais rápidas.

Então, é possível adicionar muitos índices? - Depende :) Te dei meus resultados - Você decide!

nightcoder
fonte
Isso não deve ser considerado uma profecia sem todos os detalhes. Especialmente porque você não pode multiplicar o ganho / perda de desempenho de uma ação para outra. A base permanece a mesma: adicione mais índices e suas inserções serão eventualmente mais lentas devido à recriação do índice.
SovietFrontier
3

Em última análise, quantos índices você precisa dependem do comportamento de seus aplicativos que funcionam no servidor de banco de dados.

Em geral, quanto mais você insere, mais dolorosos se tornam seus índices. Cada vez que você faz uma inserção, todos os índices que incluem aquela tabela devem ser atualizados.

Agora, se o seu aplicativo tiver uma quantidade decente de leitura, ou ainda mais se for quase toda leitura, os índices são o caminho a seguir, pois haverá grandes melhorias de desempenho por um custo muito baixo.

Orion Adrian
fonte
3

Não há uma resposta estática na minha opinião, esse tipo de coisa se enquadra no 'ajuste de desempenho'.

Pode ser que tudo o que o seu aplicativo faz seja pesquisado por uma chave primária, ou pode ser o contrário, pois as consultas são feitas sobre combinações de campos não restritas e qualquer um em particular pode ser usado a qualquer momento.

Além de apenas indexar, há a reogranização de seu banco de dados para incluir campos de pesquisa calculados, tabelas de divisão, etc - é realmente dependente de seus formatos de carga e parâmetros de consulta, quanto / quais dados "realmente" precisam ser recuperados por uma consulta.

Se todo o seu banco de dados é fronteado por fachadas de procedimento armazenado, a rotação se torna um pouco mais fácil, pois você não precisa se preocupar com cada consulta ad-hoc. Ou você pode ter uma compreensão profunda do tipo de consultas que atingirão seu banco de dados e pode limitar o ajuste a elas.

Para o SQL Server, achei o Orientador de Otimização do Mecanismo de Banco de Dados útil - você configura cargas de trabalho 'típicas' e ele pode fazer recomendações sobre como adicionar / remover índices e estatísticas. Tenho certeza de que outros bancos de dados possuem ferramentas semelhantes, sejam "oficiais" ou de terceiros.

Escócia
fonte
3

Esta é realmente uma questão mais teórica do que prática. O impacto dos índices no seu desempenho depende do hardware que você possui, da versão do Oracle, dos tipos de índice, etc. Ontem ouvi que a Oracle anunciou um armazenamento dedicado, feito pela HP, que deve funcionar 10 vezes mais rápido com o banco de dados 11g. Quanto ao seu caso, podem haver várias soluções: 1. Ter uma grande quantidade de índices (> 20) e reconstruí-los diariamente (noturno). Isso seria especialmente útil se a tabela obtiver milhares de atualizações / exclusões diariamente. 2. Particione sua tabela (se isso se aplicar ao seu modelo de dados). 3. Use uma tabela separada para dados novos / atualizados e execute um processo noturno que combina os dados. Isso exigiria uma mudança na lógica do aplicativo. 4. Mude para IOT (tabela organizada de índice), se seus dados suportarem isso.

É claro que pode haver muito mais soluções para esse caso. Minha primeira sugestão para você, seria clonar o banco de dados para um ambiente de desenvolvimento e executar alguns testes de estresse contra ele.

Moshe
fonte
Não entendo como a reconstrução dos índices ajudaria, ou como um IOT ajudaria.
David Aldridge
IOT - se for possível redesenhar o aplicativo, de modo que um novo tipo de dados definido pelo usuário seja usado, então o IOT economizaria a sobrecarga em torno da indexação da tabela. pode não ser o caso aqui. realmente depende. reconstruindo o índice - caso haja muitos índices e novos dados não sejam indexados.
Moshe
Um IOT ainda é uma estrutura de índice, com mais sobrecarga nas divisões de bloco do que um índice regular. "reconstruindo o índice - caso haja muitos índices e novos dados não sejam indexados" ... de qual RDBMS você está falando que não mantém índices automaticamente para novas entradas?
David Aldridge,
David - você está certo, é claro. Combinei isso com a capacidade do SQL Server de indexar Full Text Search apenas por demanda. Gostaria que a Oracle o tivesse, já que poderia ser útil neste caso. Eu recomendo ficar com as outras duas sugestões.
Moshe
2

Se você faz mais leituras (e poucas atualizações), não há realmente nenhuma razão para não indexar tudo que você precisa indexar. Se você atualiza com frequência, deve ter cuidado com a quantidade de índices que possui. Não existe um número difícil, mas você notará quando as coisas começarem a desacelerar. Certifique-se de que seu índice clusterizado seja o que faz mais sentido com base nos dados.

Bob King
fonte
2

Uma coisa que você pode considerar é construir índices para direcionar uma combinação padrão de pesquisas. Se a coluna1 for comumente pesquisada e a coluna2 for frequentemente usada com ela e a coluna3 às vezes for usada com a coluna2 e coluna1, então um índice na coluna1, coluna2 e coluna3 nessa ordem pode ser usado para qualquer uma dessas três circunstâncias, embora seja apenas um índice que deve ser mantido.

Jeffrey L Whitledge
fonte
2

Um índice impõe um custo quando a tabela subjacente é atualizada. Um índice fornece um benefício quando é usado para acelerar uma consulta. Para cada índice, você precisa equilibrar o custo em relação ao benefício. Quanto mais lenta a consulta é executada sem o índice? Quanto de um benefício está funcionando mais rápido? Você ou seus usuários podem tolerar a velocidade lenta quando o índice está ausente?

Você pode tolerar o tempo adicional necessário para concluir uma atualização?

Você precisa comparar custos e benefícios. Isso é particular para sua situação. Não existe um número mágico de índices que ultrapasse o limite de "muitos".

Também há o custo do espaço necessário para armazenar o índice, mas você disse que na sua situação isso não é um problema. O mesmo é verdade na maioria das situações, dado o quão barato o espaço em disco se tornou.

Walter Mitty
fonte
1

Quantas colunas existem? Sempre me disseram para criar índices de coluna única, não índices de várias colunas. Portanto, não há mais índices do que a quantidade de colunas, IMHO.

lamcro
fonte
1

O que realmente importa é não adicionar um índice a menos que você saiba (e isso geralmente significa reunir estatísticas de uso) que ele será usado com muito mais frequência do que atualizado.

Qualquer índice que não atenda a esses critérios custará mais para reconstruir do que a penalidade de desempenho de não tê-lo no caso estranho de ser usado.

Torbjörn Gyllebring
fonte
1

O servidor SQL oferece algumas boas ferramentas que permitem ver quais índices estão realmente sendo usados. Este artigo, http://www.mssqltips.com/tip.asp?tip=1239 , fornece algumas consultas que permitem obter uma visão melhor de quanto um índice é usado, em oposição ao quanto é atualizado.

aboy021
fonte
0

É totalmente baseado nas colunas que estão sendo usadas na cláusula Where. E como o polegar da regra, devemos ter índices em colunas de chave estrangeira para evitar DEADLOCKS. O relatório AWR deve ser analisado periodicamente para entender a necessidade de índices.

P Sharma
fonte
2
Índices em colunas de chave estrangeira para evitar deadlocks? Você tem uma referência que explica por que e como isso ocorre?
Jay Sullivan