A adição de índice na coluna de bits desacelera significativamente as inserções?

11

Eu tenho uma tabela com cerca de 1 a 5 milhões de registros. Uma pequena parte desses registros possui uma coluna de bits definida como 'TRUE'. Precisa encontrar rapidamente esses registros. Eu acho que esse índice pode acelerar a pesquisa nessa coluna, mas eu tenho medo dos INSERTs. Daí a minha pergunta.

O banco de dados está funcionando como uma espécie de armazém de dados; portanto, existem muitos SELECTs e INSERTs pequenos (até 10 a 20 por dia), mas bastante grandes (até 200 mil registros ao mesmo tempo). Eu tenho medo de mais tempo dessas importações para o banco de dados.

marioosh
fonte
5
Qual versão do SQL Server? Se 2008+ parece um índice filtrado, pode ser o que você precisa.
Martin Smith
SQL Server 2005
marioosh 14/02
1
Você pode dividir a tabela (adicione uma nova tabela com apenas uma coluna, a PK da tabela, que seria preenchida apenas com as linhas em que a coluna de bits é verdadeira - no final, você pode até remover a coluna de bits.) Essa visão funcionaria, assim como em 2005, com a falta de índices parciais.
ypercubeᵀᴹ
tenha cuidado com o Indexed View, como você mencionou que tem de 10 a 20 pastilhas grandes por dia, a manutenção do Indexed View pode superar os benefícios do ganho de desempenho. Eu não acho que nenhum recurso "pronto para uso" do SQL 2005 possa ser utilizado para melhorar sua situação. mas se você listar a estrutura atual da tabela e o índice existente, podemos encontrar algum design alternativo.
Anup Shah

Respostas:

8

Um índice de 1 milhão de registros é inútil. O otimizador nunca o usará, você pagará apenas pela manutenção. Uma alternativa muito melhor é adicionar esse bit como a chave mais à esquerda no índice em cluster.

Mas farei um tiro cego no escuro e acho que o que você tem é um padrão de fila: os registros são descartados na tabela com o bit definido como 'TRUE' (ou seja, 'needsprocessing = true') e, em seguida, um processo em segundo plano parece para esses registros, realiza algum processamento e atualiza o bit para FALSE. Esse é um padrão onipresente, também conhecido carinhosamente como o 'padrão de receita de desastre de desempenho'. Eu recomendaria soltar os registros na tabela e soltar uma notificação (poderia ser tão simples quanto o ID do registro recém-inserido), ao mesmo tempo, em uma fila . Consulte Usando tabelas como filas .

Remus Rusanu
fonte
1
Não estou vendo nenhum bom ponto em colocar a coluna de bits no lado esquerdo, pois não conhecemos outras colunas de filtro com alta cardinalidade que o usuário possa ter. até agora eu vi coluna BIT é a última opção no índice de cluster. mas sim, +1 para a boa referência de "Usar tabela como filas".
Anup Shah
2
Na verdade, eu fiz um teste e sim, ele usará o índice. Crie uma tabela (identidade de ID, bit myBit) e adicione 100 linhas onde o bit é 0 e 2000000 onde o bit é 1. Verifique se as estatísticas são atualizadas (se necessário) e execute uma consulta em myBit = 0 e o índice será usado.
21414 Kenneth Fisher
@KennethFisher, exceto que no padrão típico de alta velocidade da inserção TRUE / update para FALSE imediatamente, as estatísticas sempre estarão desatualizadas. Se você preferir jogar roleta russa com o otimizador em vez de fazer um projeto claro, você vai ter o que merece ...
Remus Rusanu
"nunca vai usá-lo", essa declaração é válida para 99% dos casos, mas não sabemos em que caso o OP está. Eu indexei com êxito o bit. Existem casos de uso.
22414 $ usr $
question - a resposta aqui está errada, especificamente> "Quando você indexa um campo de bits (ou algum intervalo estreito), você reduz apenas o conjunto de trabalho pelo número de linhas que correspondem a esse valor. Se você tiver um número pequeno de linhas que o correspondam reduziria muito o seu conjunto de trabalho . Para um grande número de linhas com distribuição 50/50, pode comprar muito pouco ganho de desempenho versus manter o índice atualizado. " Nesse caso, um índice que corresponda a 1% dos registros evitaria a necessidade de verificar 99% de 1 milhão para obter um aumento significativo?
drzaus
2

Como o @MartinSmith disse, se você atualizar para o SQL 2008, um índice filtrado seria a solução perfeita. No entanto, nesse meio tempo, como um caso geral, QUALQUER índice adicionado aumentará o tempo de carregamento. Índices pequenos menos que os grandes.

Uma coisa que eu observaria é se você tem um índice existente que pode ser modificado. Supondo que suas consultas existentes estejam usando um determinado índice, a adição da coluna de bits ao final desse índice deve ter um efeito mínimo nas inserções e o efeito positivo que você procura nas suas consultas.

A próxima coisa a considerar é "Já tenho muitos índices?" Não existe uma regra rígida e rápida sobre o que é "muito", mas eu costumo seguir uma regra de 10 índices, a menos que eu realmente precise de um novo.

Por último, teste-o em uma instância de teste. Configure uma tabela com alguns milhões de linhas, execute sua carga nela, adicione seu índice, execute sua carga novamente e veja se você percebe um aumento significativo no tempo de carregamento.

Somente você pode realmente decidir o que é "significativo". Eu tenho máquinas em que adicionar 5 minutos ao tempo de carregamento é "significativo" e outras em que pude ver com segurança um aumento de duas horas.

EDITAR:

Outra opção é particionar sua tabela. Pode ser necessário usar uma exibição particionada se você não estiver usando a edição Enterprise, mas mesmo assim deve ajudar. Você coloca seu bit 0s em uma partição e seu bit 1s em outra. Supondo que você esteja inserindo apenas uma versão ou outra, você poderá até acelerar suas inserções.

Kenneth Fisher
fonte