É otimização prematura adicionar índices de banco de dados?

61

Um colega meu hoje sugeriu que passássemos por todas as consultas em nosso aplicativo e adicionássemos índices de acordo.

Eu sinto que isso é otimização prematura, porque nosso aplicativo ainda não foi lançado. Sugeri monitorar consultas lentas quando entrarmos no ar e adicionar índices de acordo.

Qual é o consenso geral ao projetar seu banco de dados, você deve adicionar um índice correspondente sempre que escrever uma nova consulta? Ou é melhor apenas monitorar e ver como vai?

Marco de Jongh
fonte
32
Pode ser uma questão de opinião, no entanto, acho que alguns índices podem ser adicionados a priori.
Basile Starynkevitch 24/02
2
@BasileStarynkevitch Concordo totalmente que já temos índices de chave primária e os trabalhos. Mas onde você desenha a linha?
Marco de Jongh 24/02
11
Meus dois centavos de experiência: eu estava testando algumas das minhas consultas de pesquisa inicial em um subconjunto do nosso banco de dados. Os testes que fiz foram totalmente bons na minha cópia local. Enviei o aplicativo para a área de teste que hospeda o banco de dados completo. Meus testes foram executados em <500 ms , enquanto o sistema de preparação demorou alguns minutos para resolver. Meu chefe ficou completamente confuso sobre o motivo pelo qual o aplicativo não estava carregando. As operações do tipo Explain são seu amigo ... Pelo menos, procure varreduras seqüenciais em tabelas grandes, pelo menos!
Chris Cirefice
2
Não adicionar índices é como usar o bubblesort. Na maioria das vezes, você não encontra nenhum problema ao testá-lo, mas quando o programa começa a aumentar ao vivo, você enfrenta muitos problemas. E os índices podem facilmente fazer um fator 100 na diferença de velocidade.
Pieter B
3
Lembre-se sempre: um índice não é uma coisa mágica que irá acelerar suas consultas. Um índice aumentará o custo na maioria das operações DML e, dependendo do tipo, pode levar a muitas esperas quando muitas pessoas atualizam a mesma tabela. Para consultas: existem muitas consultas que não se beneficiam de um índice, em que um STF é o mais rápido ou em que o particionamento faz todo o trabalho para você. - Adicione apenas um índice onde você SABE que será benéfico!
Falco

Respostas:

132

A otimização prematura está "otimizando" alguma coisa por causa de uma sensação vaga e intuitiva de que, provavelmente, isso será lento, especialmente em detrimento da legibilidade e manutenção do código . Isso não significa deliberadamente não seguir boas práticas bem estabelecidas em relação ao desempenho.

Às vezes é difícil traçar uma linha, mas eu definitivamente diria que não adicionar nenhum índice antes de você entrar no ar é uma otimização muito tarde ; isso punirá os adotantes iniciais - seus usuários mais ansiosos e mais importantes - e fornecerá a eles uma visão negativa do seu produto, que eles espalharão em análises, discussões etc. O monitoramento de consultas para encontrar pontos problemáticos que precisam de indexação é um boa ideia, mas eu faria isso o mais tardar na versão beta.

Mason Wheeler
fonte
11
Sim, isso deve ser feito na fase de teste de carga
Alvaro
152
A otimização antes que você saiba onde estão as partes lentas é a otimização prematura. Liberar a coisa antes que você saiba onde estão as partes lentas é uma liberação prematura !
MatemáticoOrchid
4
@ MathematicsOrchid: Essa é uma ótima frase! Posso emprestá-lo em outro lugar?
Pieter Geerkens
3
@PieterGeerkens Claro, nocauteie-se! ;-) Estou triste que 91+ upvotes não me valem nenhuma reputação ... heh.
MatemáticoOrchid
3
@MathematicsOrchid deveria ter sido uma resposta. Poderia concorrer à resposta "menor e mais direta ao ponto" de todos os tempos.
Mindwin
48

monitorar consultas lentas assim que entrarmos no ar

porque nada diz qualidade como fazer seus usuários sofrerem por falta de design!

Você deve saber quais consultas precisam de índices ao criar as tabelas, quais colunas estão sendo consultadas nas cláusulas where e nas junções. Eles já devem estar indexados, porque o que pode não ser aparente em um ambiente ativo pode rapidamente se tornar aparente quando a carga ou os dados armazenados aumentam. O que você não quer fazer quando isso acontece é aplicar índices em todas as consultas "lentas"; você terminará com um índice em tudo.

gbjbaanb
fonte
10
Direito. Considere índices como parte do design do banco de dados. Use índices para evitar uma varredura completa da tabela para qualquer consulta que o usuário final faça normalmente em tempo real.
AE
11
@DocBrown Eu não tenho tanta certeza, quando você cria uma tabela, você tem (ou deveria ter) alguma compreensão de como será usada. Uma tabela de pessoa será consultada por ID ou possivelmente sobrenome. Se alguém começar a acessar via DoB, endereço ou número de telefone, você adicionará índices para todos os campos - e onde isso termina ?!
Gbjbaanb
4
@gbjbaanb: termina quando as pessoas param de adicionar recursos ao produto, o que pode ser "nunca", dependendo da sua metodologia.
Steve Jessop
11
@SteveJessop, quero dizer que você indexa de acordo com as colunas principais que deseja acessar. Para uma tabela de pessoas, você pode ter uma função de pesquisa (se você esquecer seu nome de usuário, poderá procurar por e-mail, por exemplo), mas depois sempre usará o ID. Portanto, o ID é o único que precisa de indexação. Se você pesquisar muitas vezes em outros campos, poderá querer um índice, isso sairá a tempo, mas geralmente você não deseja indexar todas as colunas apenas porque alguém decidiu algum dia escrever uma consulta fora do padrão, mas pode utilize um mecanismo diferente para esses casos "únicos".
Gbjbaanb
2
@gbjbaanb: claro, as pessoas não devem procurar repetidamente o mesmo sobrenome em uma tabela, por ser uma alça marginalmente mais conveniente para elas segurar do que a chave apropriada para a mesa. Eu diria que esse é o caso, independentemente de a tabela ser indexada por sobrenome ou não, pois há algo muito suspeito em um trecho de código que pressupõe que tudo esteja operando no "mesmo usuário", mas não consegue expressar isso em código por lembrar o ID :-) Eu estava imaginando casos em que a necessidade de pesquisa inversa não estava previsto até que o cliente mencionou ...
Steve Jessop
26

"Otimização prematura", em seu sentido depreciativo, significa otimização dispendiosa que pode não ser necessária. Isso não significa toda a otimização implementada antes do último ponto possível para evitar a falência!

Em particular, é legítimo otimizar com base em testes de desempenho antes de entrar no ar, para garantir que você atenda a alguns requisitos sensatos (embora aproximados) para que seu aplicativo não seja totalmente ruim.

No mínimo absoluto, você deve carregar seu banco de dados com uma quantidade plausível de dados de teste e verificar a capacidade de resposta do seu aplicativo. Isso não é prematuro, já que você sabe que isso vai acontecer e ele captura todas as consultas que disparam verificações absurdamente lentas. Como AE diz em um comentário:

Use índices para evitar uma varredura completa da tabela para qualquer consulta que o usuário final faça normalmente em tempo real

Pelo menos, para tabelas planejadas para crescer em uso.

Então, como atalho para isso, se você tiver uma experiência significativa com o mecanismo de banco de dados e já tiver planejado os testes ao escrever o primeiro corte do código, muitas vezes saberá, mesmo sem executá-lo, que a consulta que está sendo executada a escrita será muito lenta sem um índice. É claro que você pode fingir que não sabe e assistir ao teste falhar antes de adicionar o índice para fazê-lo passar, mas não há motivo para que o código defeituoso conhecido (porque não responde) seja lançado.

Steve Jessop
fonte
20

Eu sinto que isso é otimização prematura, porque nosso aplicativo ainda não foi lançado. Sugeri monitorar consultas lentas quando entrarmos no ar e adicionar índices de acordo.

Você não pode tratar os usuários finais e o ambiente de produção como garantia de qualidade. Em mais palavras, você está dizendo que descobrirá em produção. Não acho que seja o caminho certo e vejo essa abordagem terrivelmente errada todos os dias .

Você precisa ter uma coisa em mente, pois não pode pintar isso com um pincel largo.

Qual é a sua carga de trabalho comum ?

Isso pode parecer óbvio ou chato, mas é significativo na prática. Se você tiver 10 consultas que representam 98% de sua carga de trabalho (bastante comum, acredite ou não), minha recomendação seria uma análise difícil antes da produção . Com dados realistas e representativos, verifique se as 10 consultas são as melhores possíveis ( perfeita é uma perda de tempo valioso e quase impossível de ser realizada).

Para as outras 200 consultas que compõem os 2% da carga de trabalho , essas são provavelmente as que não valem muito esforço e compõem as peculiaridades da solução de problemas na produção. Isso também é uma realidade, e não uma coisa terrivelmente ruim. Mas isso não significa ignorar as práticas recomendadas de indexação nem fazer suposições estimadas sobre a recuperação de dados.

É comum e uma boa prática descobrir o desempenho do banco de dados antes da produção. De fato, existe uma posição relativamente comum para esse tipo de coisa chamada DBA de desenvolvimento .

Mas...

Alguns levam isso longe demais e ficam loucos adicionando índices "por precaução". Alguém recomenda que este índice esteja faltando? Adicione-o e outras quatro variações. Também é uma má ideia. Você precisa pensar não apenas na recuperação de dados, mas também na modificação de dados? Quanto mais índices você tiver em uma tabela, geralmente falando, mais sobrecarga você terá quando modifica dados.

Como a maioria das coisas, há um equilíbrio saudável.

Como uma pequena anotação divertida ... A pluralização de "Índice"

"Índices" são para pessoas financeiras

"Índices" são para nós

Thomas Stringer
fonte
2
Isso precisa de mais votos. Eu não poderia concordar mais.
precisa
+1 no bit "just in case" (isso seria uma otimização prematura). Se eu pudesse, eu votaria novamente no bit "carga de trabalho comum".
David
Espero que você saiba de antemão quais 10 consultas pertencem aos 98% e quais não.
Pa Elo Ebermann 27/02
@ PaŭloEbermann A maioria dos DBMS 'tem a capacidade de capturar essas informações de maneira rápida e fácil. Nesse caso, não há desculpa para não saber.
Thomas Stringer
@ThomasStringer Obviamente, isso só funcionará se os casos de teste antes da produção estiverem de alguma forma relacionados ao que é feito por usuários reais na produção.
Pa Elo Ebermann 27/02
4

Não, não é uma otimização prematura, mas deve ser feita corretamente, como qualquer otimização deve ser.

Aqui está o que eu faria:

  1. Carregue o banco de dados com dados de teste suficientes para imitar uma carga de produção. Você não pode obter 100% de precisão, mas tudo bem: basta inserir dados suficientes. Uma tabela possui uma quantidade fixa de dados? Carregue-o. Você tem uma tabela que contém muitos dados, por exemplo, qualquer tabela que contenha perguntas neste site? Carregue alguns milhões de registros, mesmo que sejam apenas dados fictícios.
  2. Ative a criação de perfil no servidor de banco de dados.
  3. Surpreenda-se com o aplicativo usando uma combinação de scripts automatizados (fornece volume) e usuários reais (eles sabem como quebrar as coisas).
  4. Revise os dados de criação de perfil. As consultas específicas são lentas? Verifique os planos de explicação e veja se o servidor de banco de dados está lhe dizendo que deseja um índice, mas ele não existe.

Os servidores de banco de dados são peças de software complexas e inteligentes. Eles podem dizer como otimizá-los, se você souber ouvir.

As chaves são medir o desempenho antes e depois da otimização e deixar o banco de dados informar o que ele precisa .


fonte
3

Seguir padrões comprovados para problemas conhecidos (como encontrar um registro por seu ID) não é nada prematuro. É sensato.

Dito isto, os índices nem sempre são um negócio direto. Muitas vezes, é difícil saber durante a fase de design quais índices dependerão do tráfego e quais serão as operações de gravação de gargalo. Então, eu argumentaria por aproveitar algumas práticas recomendadas "óbvias" de design de esquema (use PKs apropriadas para os padrões de leitura / gravação projetados e indexe FKs); mas não coloque um índice em mais nada até que o teste de estresse o exija.

svidgen
fonte
Gastar mais 30 segundos para fazer algo que quase certamente melhora o desempenho e dificilmente prejudicá-lo não é "otimização prematura". Se 90% das operações em uma tabela usarem uma coluna específica como chave, a indexação melhorará o desempenho ou o desempenho nunca será lento o suficiente para importar, e adicionar código para criar o índice poderá levar menos tempo do que determinar se é realmente necessário.
supercat
@supercat "nunca" ... Até que você começar a ver os impasses em seu ambiente de produção ...
svidgen
Que tipo de cenário realista você imagina que seria consistente com 90% das operações usando uma coluna como chave e onde a adição de um índice causaria um impasse?
supercat 25/02
@ supercat Eu não tenho certeza se entendi completamente sua busca. Em termos de um aplicativo ativo, quase qualquer aumento no tempo de execução ou no número de ios tem o potencial de introduzir deadlocks. ... Mas, mais importante, a presença ou ausência de um índice na maioria dos aplicativos é insignificante até que o banco de dados atinja um tamanho crítico e / ou nível de simultaneidade. Por exemplo, quando todos os seus índices já não cabem na memória ...
svidgen
11
O ponto é que é difícil saber qual é a composição da sua consulta até que casos de uso típicos sejam executados por um teste de estresse (ou até que você veja problemas com o comportamento inesperado do usuário na produção). Se você tiver uma página que exclui tablex.fieldy, mas é atingida apenas uma vez a cada mil inserções ... O índice pode resultar em uma degradação líquida.
Svidgen
2

Quando seu aplicativo é lançado, é tarde demais.

Mas qualquer processo de desenvolvimento adequado deve incluir testes de desempenho.

Use os resultados de seus testes de desempenho para decidir quais índices adicionar e verifique sua eficácia repetindo os testes de desempenho.

Philipp
fonte
Quando um aplicativo é lançado, é realmente um bom momento para ajustar os índices. Olhe para este site, stachexchange, você pode apostar que os índices mudaram muito tempo após o lançamento.
LosManos 25/02
@ LosManos: Ninguém paga para usar o Stack Exchange.
Lightness Races com Monica
@LightnessRacesinOrbit: O contrário, os anunciantes pagam para usar o Stack Exchange.
@ JonofAllTrades: Eles não se importam se temos algumas horas de desempenho ruim devido a um índice ausente. O que quero dizer é que um site grande, gratuito e orientado para a comunidade, com um ciclo de distribuição perpétuo, é muito diferente de um produto comercial independente e lançado periodicamente. Portanto, SE não é um bom exemplo.
Lightness Races com Monica
1

Embora eu não ache que todas as consultas devam ser otimizadas, os índices fazem parte do RDBMS que precisam ser considerados antes da liberação. Quando você executa uma consulta, diferentemente de outras formas de programação, você não está dizendo ao sistema como executá-la. Eles desenvolvem planos próprios e quase sempre o baseiam na disponibilidade de um índice. A composição e o volume dos dados também serão considerados posteriormente.

Aqui estão algumas coisas que eu consideraria:

  1. Existem algumas perguntas que você deve identificar no seu desenvolvimento inicial que você sabe que serão usadas com freqüência. Concentre-se neles.
  2. Haverá consultas lentas. Ao indexá-los primeiro, você pode determinar se o desempenho ainda não é rápido o suficiente e considerar uma reformulação (a desnormalização pode ser prematura). Prefiro fazer isso antes do lançamento. Ninguém quer um sistema em que sejam necessários 10 minutos para encontrar algo no inventário.
  3. Os índices podem melhorar o desempenho da consulta, mas não impedem a modificação dos dados.
  4. Muitos sistemas possuem ferramentas para analisar suas consultas, portanto, não tenha medo de usá-las.

Após sua revisão inicial, você deve segui-lo com algumas considerações sobre quando deve revisá-lo novamente e como poderá coletar as informações para fazer isso (monitorar o uso, obter cópias dos dados do cliente etc.).

Sei que você não deseja otimizar prematuramente, mas é quase certo que você terá um desempenho ruim sem indexar seu banco de dados. Ao tirar isso do caminho, você pode determinar se há outras áreas causando problemas de desempenho.

JeffO
fonte
0

Também depende de quantos usuários você espera. Você definitivamente deve fazer alguns testes de carga e garantir que seu banco de dados possa acompanhar de 10 a 100 a 1000s de solicitações simultâneas. Novamente, isso depende da quantidade de tráfego que você espera e de quais áreas você espera que sejam usadas mais do que outras.

Em geral, eu ajustaria as áreas que eu espero que o usuário atinja primeiro. Então, eu ajustava tudo que fosse lento do ponto de vista da experiência do usuário. Sempre que o usuário tiver que esperar por algo, ele terá uma experiência ruim e poderá ser recusado. Não é bom!

harsimranb
fonte
0

É uma boa prática identificar quais colunas definitivamente precisam de um índice por algumas análises iniciais. Existe um risco real de degradação gradual ou inesperada do desempenho na produção, à medida que o tamanho do banco de dados aumenta se você não tiver absolutamente nenhum índice. A situação que você deseja evitar é o local em que uma consulta executada geralmente exige a varredura de um grande número de linhas da tabela. Não é uma otimização prematura adicionar índices a colunas críticas, pois você possui muitas das informações necessárias disponíveis e as possíveis diferenças de desempenho são significativas (ordens de magnitude). Também há situações em que o benefício dos índices é menos claro ou mais dependente dos dados - você pode adiar a decisão para alguns desses casos.

Algumas perguntas que você precisa fazer são:

  • Quais são os limites de design para o tamanho de cada tabela?

Se as tabelas sempre forem pequenas (digamos <100 linhas), não será um desastre se o banco de dados precisar varrer a tabela inteira. Pode ser benéfico adicionar um índice, mas isso requer um pouco mais de experiência ou medição para determinar.

  • Com que frequência cada consulta será executada e qual é o tempo de resposta necessário?

Se a consulta for executada com pouca frequência e não tiver requisitos rígidos de tempo de resposta (por exemplo, geração de relatórios) e o número de linhas não for grande, provavelmente será bastante seguro adiar a adição de índices. Novamente, a experiência ou a medição podem ajudar a dizer se será benéfico.

  • A consulta requer que você procure na tabela algo além da chave primária? Por exemplo, filtragem por período, ingressando em uma chave estrangeira?

Se essas consultas forem executadas com frequência e tocarem em tabelas com muitas linhas, considere seriamente adicionar preventivamente um índice. Se você não tiver certeza se esse é o caso de uma consulta, você pode preencher o banco de dados com uma quantidade realista de dados e examinar o plano de consulta.

user611910
fonte