Quais colunas geralmente são bons índices?

98

Na sequência de " O que são índices e como posso usá-los para otimizar consultas em meu banco de dados? ", Onde estou tentando aprender sobre índices, quais colunas são boas candidatas a índice? Especificamente para um banco de dados MS SQL?

Depois de pesquisar no Google, tudo o que li sugere que as colunas que geralmente aumentam e são únicas formam um bom índice (coisas como auto_incremento do MySQL), eu entendo isso, mas estou usando MS SQL e estou usando GUIDs para chaves primárias, pelo que parece que os índices não beneficiariam as colunas GUID ...

mmattax
fonte
Que tal um "livro de receitas": mysql.rjweb.org/doc.php/index_cookbook_mysql
Rick James

Respostas:

110

Os índices podem desempenhar um papel importante na otimização de consultas e na pesquisa rápida de resultados nas tabelas. Portanto, é a etapa mais importante selecionar quais colunas serão indexadas. Existem dois lugares principais onde podemos considerar a indexação: colunas referenciadas na cláusula WHERE e colunas usadas nas cláusulas JOIN. Em suma, essas colunas devem ser indexadas em relação às quais você deve pesquisar registros específicos. Suponha que temos uma tabela chamada compradores em que a consulta SELECT usa índices como abaixo:

SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

Visto que "buyer_id" é referenciado na parte SELECT, o MySQL não o usará para limitar as linhas escolhidas. Portanto, não há grande necessidade de indexá-lo. A seguir está outro exemplo um pouco diferente do anterior:

SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

De acordo com as consultas acima first_name, as colunas last_name podem ser indexadas, pois estão localizadas na cláusula WHERE. Além disso, um campo adicional, country_id da tabela de país, pode ser considerado para indexação porque está em uma cláusula JOIN. Portanto, a indexação pode ser considerada em todos os campos da cláusula WHERE ou da cláusula JOIN.

A lista a seguir também oferece algumas dicas que você deve sempre ter em mente quando pretende criar índices em suas tabelas:

  • Apenas indexe as colunas que são necessárias nas cláusulas WHERE e ORDER BY. A indexação de colunas em abundância resultará em algumas desvantagens.
  • Tente tirar proveito do "prefixo de índice" ou do recurso de "índice de múltiplas colunas" do MySQL. Se você criar um índice como INDEX (first_name, last_name), não crie INDEX (first_name). No entanto, "índice de prefixo" ou "índice de múltiplas colunas" não é recomendado em todos os casos de pesquisa.
  • Use o atributo NOT NULL para as colunas nas quais você considera a indexação, para que os valores NULL nunca sejam armazenados.
  • Use a opção --log-long-format para registrar consultas que não estão usando índices. Desta forma, você pode examinar este arquivo de log e ajustar suas consultas de acordo.
  • A instrução EXPLAIN ajuda a revelar como o MySQL executará uma consulta. Mostra como e em que ordem as tabelas são unidas. Isso pode ser muito útil para determinar como escrever consultas otimizadas e se as colunas precisam ser indexadas.

Atualização (23 de fevereiro de 2015):

Qualquer índice (bom / ruim) aumenta o tempo de inserção e atualização.

Dependendo de seus índices (número de índices e tipo), o resultado é pesquisado. Se o seu tempo de pesquisa vai aumentar por causa do índice, isso é um índice ruim.

Provavelmente em qualquer livro, a "Página de Índice" poderia ter a página inicial do capítulo, o início do número da página do tópico e também o início da página do subtópico. Alguns esclarecimentos na página de índice ajudam, mas um índice mais detalhado pode confundi-lo ou assustá-lo. Os índices também têm memória.

A seleção do índice deve ser sábia. Lembre-se de que nem todas as colunas exigem índice.

Somnath Muluk
fonte
Graças Somnath, Então isso implica índices só deve ser criado para colunas onde estamos planejando usar WHERE, JOINSou HAVING?
Muhammad Babar
3
Sim, use índices para colunas nas quais você planeja usar WHERE, JOINS ou HAVING. Mas também lembre-se de que todas as colunas de condição não requerem índices. Às vezes, onde a coluna de condição é usada apenas uma vez, então pode não precisar de índice, enquanto outra coluna de condição é usada em muitas consultas, então prefira mais para indexar para essa coluna.
Somnath Muluk
1
A resposta se beneficiaria ao colocar "colunas referenciadas na cláusula WHERE e colunas usadas nas cláusulas JOIN" em uma seção TL; DR.
jpmc26
Então você está dizendo que se na minha WHEREcláusula eu estiver verificando o valor de um campo onde sua coluna só pode assumir dois valores, então devo indexar essa coluna binária? Isso parece errado.
AjaxLeung
@AjaxLeung: Lembre-se da máxima de Knuth "A Otimização Prematura é a raiz de todo o Mal.". Você pode fazer índice em colunas binárias, mas deve depender de qual custo (como inserir, atualizar tempos). Se a sua lógica de negócios frequentemente depende dessa opção binária, a coluna binária pode ser necessária para ter um índice.
Somnath Muluk
20

Algumas pessoas responderam a uma pergunta semelhante aqui: Como você sabe o que é um bom índice?

Basicamente, realmente depende de como você consultará seus dados. Você quer um índice que identifique rapidamente um pequeno subconjunto de seu conjunto de dados que é relevante para uma consulta. Se você nunca consulta por carimbo de data, não precisa de um índice, mesmo que seja exclusivo. Se tudo o que você faz é obter eventos que aconteceram em um determinado período, com certeza deseja um. Na maioria dos casos, um índice de gênero não faz sentido - mas se tudo o que você fizer for obter estatísticas sobre todos os homens e, separadamente, sobre todas as mulheres, pode valer a pena criar um. Descubra quais serão seus padrões de consulta e o acesso a qual parâmetro restringe mais o espaço de pesquisa, e esse é seu melhor índice.

Considere também o tipo de índice que você cria - as árvores B são boas para a maioria das coisas e permitem consultas de intervalo, mas os índices hash vão direto ao ponto (mas não permitem intervalos). Outros tipos de índices têm outros prós e contras.

Boa sorte!

SquareCog
fonte
9

Tudo depende de quais consultas você espera fazer sobre as tabelas. Se você solicitar todas as linhas com um determinado valor para a coluna X, terá que fazer uma varredura completa da tabela se um índice não puder ser usado.

Os índices serão úteis se:

  • A coluna ou colunas têm um alto grau de exclusividade
  • Freqüentemente, você precisa procurar um determinado valor ou intervalo de valores para a coluna.

Eles não serão úteis se:

  • Você está selecionando uma grande% (> 10-20%) das linhas da tabela
  • O uso de espaço adicional é um problema
  • Você deseja maximizar o desempenho da pastilha. Cada índice em uma tabela reduz o desempenho de inserção e atualização porque eles devem ser atualizados cada vez que os dados mudam.

As colunas de chave primária normalmente são ótimas para indexação porque são exclusivas e costumam ser usadas para pesquisar linhas.

Plasmer
fonte
pesquisas de string onde o valor pode estar em qualquer lugar dentro da string podem fazer com que não use esses índices nesse caso.
Arthur Thomas,
5

Em geral (não uso o mssql, portanto não posso comentar especificamente), as chaves primárias são bons índices. Eles são exclusivos e devem ter um valor especificado. (Além disso, as chaves primárias são índices tão bons que normalmente têm um índice criado automaticamente.)

Um índice é efetivamente uma cópia da coluna que foi classificada para permitir a pesquisa binária (que é muito mais rápida do que a pesquisa linear). Os sistemas de banco de dados podem usar vários truques para acelerar ainda mais a pesquisa, principalmente se os dados forem mais complexos do que um simples número.

Minha sugestão seria não usar nenhum índice inicialmente e traçar o perfil de suas consultas. Se uma consulta específica (como pesquisar pessoas pelo sobrenome, por exemplo) for executada com muita frequência, tente criar um índice sobre os atributos relevantes e o perfil novamente. Se houver uma aceleração perceptível nas consultas e uma desaceleração desprezível nas inserções e atualizações, mantenha o índice.

(Peço desculpas se estou repetindo coisas mencionadas em sua outra pergunta, eu não tinha descoberto antes.)

Zooba
fonte
5

Qualquer coluna que será usada regularmente para extrair dados da tabela deve ser indexada.

Isso inclui: chaves estrangeiras -

select * from tblOrder where status_id=:v_outstanding

campos descritivos -

select * from tblCust where Surname like "O'Brian%"

As colunas não precisam ser exclusivas. Na verdade, você pode obter um desempenho muito bom de um índice binário ao pesquisar exceções.

select * from tblOrder where paidYN='N'
pappes
fonte
Sua menção explícita de chaves estrangeiras realmente esclareceu as coisas para mim, considerando junções.
pfabri
3

Realmente depende de suas dúvidas. Por exemplo, se você quase só grava em uma tabela, é melhor não ter índices, eles apenas tornam as gravações mais lentas e nunca são usados. Qualquer coluna que você esteja usando para se juntar a outra tabela é uma boa candidata para um índice.

Além disso, leia sobre o recurso Índices ausentes. Ele monitora as consultas reais sendo usadas em seu banco de dados e pode dizer quais índices teriam melhorado o desempenho.

jwanagel
fonte
3

Uma coluna GUID não é a melhor candidata para indexação. Os índices são mais adequados para colunas com um tipo de dados que pode receber alguma ordem significativa, ou seja, classificados (inteiro, data, etc.).

Não importa se os dados em uma coluna geralmente aumentam. Se você criar um índice na coluna, o índice criará sua própria estrutura de dados que simplesmente referenciará os itens reais em sua tabela sem se preocupar com a ordem armazenada (um índice não agrupado). Então, por exemplo, uma pesquisa binária pode ser realizada em sua estrutura de dados de índice para fornecer uma recuperação rápida.

Também é possível criar um "índice clusterizado" que reordenará fisicamente seus dados. No entanto, você só pode ter um deles por tabela, enquanto pode ter vários índices não agrupados.

Cinza
fonte
Bem, isso não é totalmente preciso dessa forma. Você pode criar facilmente um índice regular não agrupado em uma coluna GUID - por que não? O GUID tem uma grande desvantagem se você usá-lo como a chave de cluster (por exemplo, para CLUSTERED INDEX) - então é um desaster de usar.
marc_s
1

A velha regra era colunas muito usadas nas cláusulas WHERE, ORDER BY e GROUP BY, ou qualquer uma que parecesse ser usada com frequência em junções. Lembre-se de que estou me referindo a índices, NÃO à chave primária

Sem querer dar uma resposta 'baunilha', mas realmente depende de como você está acessando os dados

Curtisk
fonte
1

Sua chave primária deve ser sempre um índice. (Eu ficaria surpreso se não fosse indexado automaticamente pelo MS SQL, na verdade.) Você também deve indexar colunas por você SELECTou ORDERcom frequência; seu objetivo é a pesquisa rápida de um único valor e uma classificação mais rápida.

O único perigo real na indexação de toomuitas colunas é diminuir a velocidade das alterações nas linhas de tabelas grandes, pois todos os índices também precisam ser atualizados. Se você realmente não tiver certeza do que indexar, calcule o tempo das suas consultas mais lentas, observe quais colunas estão sendo usadas com mais frequência e indexe-as. Então veja como eles são mais rápidos.

Eevee
fonte
1

Os tipos de dados numéricos ordenados em ordem crescente ou decrescente são bons índices por vários motivos. Primeiro, os números são geralmente mais rápidos de avaliar do que as strings (varchar, char, nvarchar, etc). Em segundo lugar, se seus valores não estiverem ordenados, as linhas e / ou páginas podem precisar ser embaralhadas para atualizar seu índice. Isso é sobrecarga adicional.

Se você estiver usando o SQL Server 2005 e estiver usando identificadores exclusivos (guids), e NÃO precisar que eles sejam de natureza aleatória, verifique o tipo de identificador exclusivo sequencial.

Por último, se você está falando sobre índices clusterizados, está falando sobre o tipo de dados físicos. Se você tiver uma string como seu índice clusterizado, isso pode ficar feio.

Ian Suttle
fonte
0

Deve ser ainda mais rápido se você estiver usando um GUID. Suponha que você tenha os registros

  1. 100
  2. 200
  3. 3000
  4. ....

Se você tiver um índice (pesquisa binária, poderá encontrar a localização física do registro que está procurando no tempo O (lg n), em vez de pesquisar sequencialmente no tempo O (n). Isso ocorre porque você não sabe quais registros possui em sua mesa.

Milhous
fonte
0

O melhor índice depende do conteúdo da tabela e do que você está tentando realizar.

Tomou um exemplo Um banco de dados de membros com uma chave primária do Numnber da Previdência Social dos membros. Escolhemos o SS porque o priamry do aplicativo se refere ao indivíduo dessa forma, mas você também deseja criar uma função de pesquisa que utilizará o nome e o sobrenome dos membros. Eu sugeriria então a criação de um índice sobre esses dois campos.

Você deve primeiro descobrir quais dados irá consultar e então determinar quais dados você precisa indexar.

Joseph
fonte