Existe algum ganho de desempenho na indexação de um campo booleano?

103

Estou prestes a escrever uma consulta que inclui um WHERE isok=1. Como o nome indica, isoké um campo booleano (na verdade, um TINYINT(1) UNSIGNEDque é definido como 0 ou 1 conforme necessário).

Existe algum ganho de desempenho na indexação deste campo? O mecanismo (InnoDB neste caso) teria um desempenho melhor ou pior procurando o índice?

Niet the Dark Absol
fonte
possível duplicata de campos booleanos
Maxim Krizhanovsky

Respostas:

80

Na verdade não. Você deve pensar nisso como um livro. Se houvesse apenas 3 tipos de palavras em um livro e você indexasse todas elas, você teria o mesmo número de páginas de índice que as páginas normais.

Haveria um ganho de desempenho se houver relativamente poucos registros de um valor. Por exemplo, se você tiver 1000 registros e 10 deles forem verdadeiros, seria útil se você pesquisar comisok = 1

Como Michael Durrant mencionou, também torna as gravações mais lentas.

EDIT: Possível duplicação: Indexação de campos booleanos

Aqui ele explica que mesmo se você tiver um índice, se você tiver muitos registros, ele não usará o índice de qualquer maneira. MySQL não usa índice ao verificar = 1, mas o usa com = 0

Michael Koper
fonte
4
Parece "sim: 2 - não: 1". Alguém está errado aqui, mas quem?
Niet the Dark Absol
4
Isso não é totalmente correto, sem um índice, o mySql precisa varrer toda a tabela para encontrar as linhas relevantes.
ilanco
4
caso contrário, ele examinaria todo o índice. (que é tão longo na maioria dos casos)
Michael Koper
1
Isso pode fazer a diferença. Basta cortar o tempo de execução pela metade de uma consulta apenas adicionando um índice, e as gravações são raras e baratas o suficiente para não nos importarmos com a penalidade. Como com tudo, não suponha, meça (também porque os bancos de dados nem sempre se comportam como você logicamente esperava)
Eelco
6
Isso pressupõe uma distribuição igual entre TRUE e FALSE. Conforme mencionado por @oucil abaixo, se você estiver procurando por um valor booleano que é bastante raro, ainda pode demorar um pouco. Não estou dizendo que você deve sempre indexar, mas presumo que a natureza de seus dados e suas consultas também sejam importantes na maioria dos mecanismos de banco de dados.
mahemoff
118

Só para esclarecer várias outras respostas aqui, já que, na minha experiência, aqueles que olham para perguntas como esta estão no mesmo barco que nós, todos nós ouvimos que indexar campos booleanos é inútil, e ainda ...

Temos uma tabela com cerca de 4 milhões de linhas, apenas cerca de 1000 de cada vez terão um switch Booleano sinalizado e é isso que procuramos. Adicionar um índice em nosso campo booleano acelerou as consultas em ordens de magnitude, passou de cerca de 9+ segundos para uma fração de segundo.

oucil
fonte
Sim, embora você deva definitivamente tentar entender o 'porquê' das coisas, sempre meça ao lado e tente coisas diferentes em seu conjunto de dados real para ver se sua teoria corresponde ao comportamento real do motor de banco de dados (você ficaria surpreso ... )
Eelco,
8
@Eelco Você está certo, mas, neste caso, o resultado realmente se encaixa bem com a teoria básica. A ideia básica de que deve ser insignificante só faz sentido se você tiver cerca de 50% de probabilidade de encontrar itens que correspondam à sua pesquisa. Então, para encontrar 100 correspondências, o banco de dados precisa iterar 200 itens. Mas se os itens corresponderem a apenas 1% do tempo, será necessário iterar 10.000 itens.
mahemoff
7
Gosto quando as pessoas realmente tentam coisas em campo e dão feedbacks sobre o ganho de desempenho, em vez de apenas filosofar.
Viktor Joras
WHERE my_col > 0 em vez de my_col = 1também parece ajudar a acelerar
Aaron,
28

Depende das consultas reais e da seletividade da combinação índice / consulta.

Caso A : condição WHERE isok = 1e nada mais lá:

SELECT *
FROM tableX
WHERE isok = 1
  • Se o índice for seletivo o suficiente (digamos que você tenha 1 milhão de linhas e apenas 1k isok = 1), o mecanismo SQL provavelmente usará o índice e será mais rápido do que sem ele.

  • Se o índice não for seletivo o suficiente (digamos que você tenha 1 milhão de linhas e mais de 100k isok = 1), o mecanismo SQL provavelmente não usará o índice e fará uma verificação de tabela.

Caso B : condição WHERE isok = 1e mais coisas:

SELECT *
FROM tableX
WHERE isok = 1
  AND another_column = 17

Então, depende de quais outros índices você tem. Um índice em another_columnprovavelmente seria mais seletivo do que o índice em isokque tem apenas dois valores possíveis. Um índice em (another_column, isok)ou (isok, another_column)seria ainda melhor.

ypercubeᵀᴹ
fonte
Eu acho que esta é a resposta mais correta em comparação com a primeira. também a distribuição dos dados.
tyan
12

Depende da distribuição dos dados.

Imagine que eu tivesse um livro com 1000 páginas digitadas com precisão, e as únicas palavras em meu livro eram 'sim' e 'não' repetidas continuamente e distribuídas aleatoriamente. Se eu fosse solicitado a circular todas as ocorrências de 'sim', um índice no final do livro ajudaria? Depende.

Se houvesse uma distribuição aleatória meio a meio de sim e não, pesquisar no índice não ajudaria. O índice tornaria o livro muito maior e, de qualquer forma, seria mais rápido apenas começar do início e trabalhar cada página procurando todas as ocorrências de "sim" e circulando-as, em vez de procurar cada item em o índice e, em seguida, tomando a referência da entrada do índice para a página a que se refere.

Mas se houvesse, digamos, apenas dez ocorrências de 'sim' em meu livro de mil páginas e todo o resto fosse apenas milhões de não, então um índice me pouparia muito tempo para encontrar essas dez ocorrências de 'sim' e circulá-las .

É o mesmo em bancos de dados. Se for uma distribuição 50:50, então um índice não vai ajudar - o mecanismo de banco de dados é melhor apenas lavando os dados do início ao fim (varredura completa da tabela), e o índice apenas aumentaria o banco de dados, e mais lento para escrever e atualizar. Mas se for algo como uma distribuição de 4000: 1 (como mostrado neste tópico), uma busca de índice pode acelerá-la enormemente, se for 1 em 4000 itens que você está procurando.

Jinlye
fonte
5

Não, geralmente não.

Normalmente, você indexa campos para pesquisa quando eles têm alta seletividade / cardinalidade. A cardinalidade de um campo booleano é muito baixa na maioria das tabelas. Isso também tornaria suas gravações um pouco mais lentas.

Michael Durrant
fonte
3

Na verdade, isso depende das consultas que você executa. Mas, geralmente sim, assim como indexar um campo de qualquer outro tipo.

Maksym Polshcha
fonte
2

Sim, um índice melhorará o desempenho, verifique a saída de EXPLAIN com e sem o índice.

Dos documentos:

Os índices são usados ​​para localizar linhas com valores de coluna específicos rapidamente. Sem um índice, o MySQL deve começar com a primeira linha e então ler toda a tabela para encontrar as linhas relevantes. Quanto maior for a mesa, maior será o custo. Se a tabela tiver um índice para as colunas em questão, o MySQL pode determinar rapidamente a posição a ser buscada no meio do arquivo de dados, sem ter que examinar todos os dados.

Eu acho que também é seguro dizer que um índice não DIMINUI o desempenho neste caso, então você só tem a ganhar com isso.

ilanco
fonte
2
Um índice fornece muitos dados no disco rígido e torna as gravações mais lentas para que você não ganhe apenas com isso.
Michael Koper
1
É verdade, mas neste caso, uma TINYINT(1) UNSIGNEDcoluna, o tamanho dos dados será pequeno.
ilanco
E a sobrecarga de gravação adicionada provavelmente muito baixa
Eelco,
O tamanho do índice não aumentará com o número de linhas para as quais ele aponta, não apenas o tamanho do campo indexado?
poolie de