Respostas:
Devo começar a indexar desde o início ou quando surgir um problema de desempenho?
A estratégia de indexação tende a evoluir à medida que surgem os padrões de uso. Dito isto, também existem estratégias e diretrizes de design que podem ser aplicadas antecipadamente.
Escolha uma boa chave de cluster . Geralmente, você pode determinar o índice clusterizado apropriado no tempo de design, com base no padrão esperado de inserções em uma tabela. Se um caso convincente surgir para uma mudança no futuro, que assim seja.
Crie suas restrições principais e outras exclusivas . Eles serão aplicados por índices exclusivos.
Crie suas chaves estrangeiras e índices não agrupados associados . Chaves estrangeiras são as colunas de junção referenciadas com mais frequência, portanto, indexe-as desde o início.
Crie índices para qualquer consulta obviamente altamente seletiva . Para padrões de consulta que você já sabe, serão altamente seletivos e provavelmente usarão pesquisas em vez de varreduras.
Além do exposto, adote uma abordagem gradual e holística para implementar novos índices. Por holística, quero dizer avaliar o potencial benefício e impacto de todas as consultas e índices existentes ao avaliar uma adição.
Um problema não incomum nos círculos do SQL Server é a superindexação, como resultado das orientações das dicas de DMVs e SSMS do índice ausentes. Nenhuma dessas ferramentas avalia índices existentes e sugere alegremente que você crie um novo índice de 6 colunas em vez de adicionar uma única coluna a um índice de 5 colunas existente.
-- If you have this
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable]
(
[col1] ASC
, [col2] ASC
, [col3] ASC
, [col4] ASC
, [col5] ASC
)
-- But your query would benefit from the addition of a column
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable]
(
[col1] ASC
, [col2] ASC
, [col3] ASC
, [col4] ASC
, [col5] ASC
, [col6] ASC
)
-- SSMS will suggest you create this instead
CREATE NONCLUSTERED INDEX [IX_MyTable_AnotherIndexWithTheSameColumnsAsTheExistingIndexPlusCol6] ON [dbo].[MyTable]
(
[col1] ASC
, [col2] ASC
, [col3] ASC
, [col4] ASC
, [col5] ASC
, [col6] ASC
)
Kimberly Tripp tem um excelente material sobre estratégia de indexação que, enquanto o foco no SQL é aplicável a outras plataformas. Para o pessoal do SQL Server, existem algumas ferramentas úteis para identificar duplicatas, como no exemplo acima.
Também podemos criar um índice temporário durante a execução de uma consulta. Quais são os prós e os contras de tais técnicas?
Isso geralmente se aplica apenas a consultas raramente executadas, geralmente ETL. Você precisa avaliar:
Há realmente riscos associados a ambas as abordagens:
Opção a) Índice desde o início, mas não percebe que você criou vários índices que nunca são usados. Isso adiciona um pouco de sobrecarga (principalmente às consultas que modificam dados, mas também com a otimização das instruções SELECT tentando identificar o melhor índice).
Você precisará se disciplinar para identificar os índices que não estão mais sendo usados e tentar removê-los (o PostgreSQL pode fazer isso; infelizmente o MySQL, por comparação, é muito fraco nesse processo).
Opção b) Não adicione índices até que as pessoas comecem a reclamar, ou suas ferramentas de diagnóstico acionam que determinadas consultas são lentas e podem ser melhoradas.
O risco que você introduz é que você não tem uma janela de tempo grande o suficiente entre o momento em que percebe que precisa do índice e quando precisa adicioná-lo.
O PostgreSQL suporta a criação de índices CONCURRENTLY
, o que reduz um pouco do estresse desse requisito de adição repentina de índice, mas há algumas ressalvas observadas no manual.
A opção (b) tende a ser a minha preferência, mas acho que um híbrido de ambas as opções é provavelmente a melhor solução. Tem a ver com o seu nível de confiança sobre se você acha que um índice será realmente usado.
O que torna essa discussão particularmente complexa é que geralmente é fácil alterar índices, mas é mais difícil alterar o esquema. Não quero promover a reação tardia de b como desculpa para ser imprudente.
Além da resposta de Mark
Você pode ter uma ideia realizando dados de teste realistas nas quantidades esperadas. Eu já vi muitos casos (muitos) em que uma consulta é executada com 1000 linhas, mas não o milhão em produção.
Se puder, trabalhe em uma cópia da produção posteriormente,
Obviamente, vi o problema estranho apenas na produção por causa dos padrões de uso quando tudo o resto é idêntico
Índices temporários? Fora dos padrões de carregamento ETL, se você precisar deles uma vez, precisará deles novamente. Não se esqueça: um índice criar / soltar é uma gravação e é registrado = mais carregamento
Apenas para adicionar algumas coisas.
Esta é a minha abordagem.
Não tenha medo de colocar > 0
ou > ""
em suas cláusulas where para colunas não utilizadas.
select * from blah
where A="one"
and B="two"
and C>="" --to match index
and D="four"
--This will use your existing index. No need to create a redundant one.
Vou tentar responder apenas a primeira pergunta. Se você puder estimar, aproximadamente desde o início, quantos registros você terá em suas tabelas após um certo período de tempo, então eu diria que é melhor começar do início para criar alguns índices. Tente usar algumas ferramentas de teste ou scripts de teste que automatizarão o maior número possível de chamadas para as chamadas de aplicativo que você acha que serão usadas com mais frequência e verá quais verificações de tabela podem ser evitadas desde o início.
Será um trabalho de adivinhação no início, mas com o tempo, como você tem estatísticas de uso adequadas, terá uma imagem mais clara.