Tipo de dados para armazenar uma matriz de sinalizadores (uma matriz de bitmap / bit)

15

Preciso armazenar uma matriz de bits para cada registro de uma tabela, suportando as seguintes operações:

  • Testando se um bit está definido e definindo um pouco (usando SQL)

  • Consultando e definindo o valor usando o ADO 2.8 (não o ADO.NET)

  • Indexação (para se beneficiar do recurso "índice de cobertura")

O número máximo de bits a serem armazenados nesta matriz é fixo, mas pode exceder 32 . Ou seja, uma coluna int simples nem sempre funciona.

Pelo que vi até agora, minhas opções são:

  1. Use várias colunas int
  2. Use bigint (funciona desde que o número de bits seja <= 64)
  3. Use binário
  4. ?

A primeira opção funcionaria, mas requer bastante refatoração no código que acessa os dados. A segunda opção é apenas um alívio temporário e, de minhas pesquisas até agora, não tenho muita certeza se o ADO funciona tão bem com bigint . Não tenho experiência com binário e não conheço outras opções.

Que tipo de dados você escolheria, considerando os requisitos?

krlmlr
fonte

Respostas:

12

Não posso advogar com força suficiente para não usar um único campo para isso.

Atualmente, estou lidando com a manutenção de um conjunto de dados muito grande com um bigint campo de máscara de bit e é um pesadelo de desempenho.

Se você verificar um pouco, tudo bem. Se você verificar mais de um bit, o desempenho diminui muito rapidamente.

Devido à natureza dos números inteiros de máscaras de bits, a distribuição de dados será muito desequilibrada e você obterá planos abaixo do ideal.

Várias verificações de bits resultam em varreduras de intervalo ou índice com uma função sendo executada em todas as linhas. É uma bagunça.

Minha solução alternativa foi simples - criei uma tabela para armazenar o PK para cada uma das condições a serem verificadas. Isso é contra-intuitivo inicialmente, mas o espaço necessário é baixo (você armazena apenas o PK) e as pesquisas são extremamente rápidas, especialmente se você usar um UNIQUE CLUSTERED INDEX.

Você pode adicionar quantas condições desejar sem afetar sua tabela principal e as atualizações também não afetam sua tabela principal.

A indexação é simples, pois você apenas indexa todas as tabelas de pesquisa individualmente e como a chave em cluster é a mesma na tabela principal e as pesquisas de todas as suas avaliações merge joinsão muito eficientes.

JNK
fonte
1
Você poderia elaborar um pouco mais sobre sua solução alternativa? Encontrei isso porque estou tentando resolver o mesmo problema básico, mas não tenho certeza da melhor maneira de fazê-lo.
Joshua Frank
4

Se tudo que você precisa armazenar for um número moderado de valores verdadeiro / falso, você poderá usar o bittipo de dados.

Internamente, o SQL Server armazena bitcolunas compactadas em "pedaços" de bytes. Portanto, para até 8 bitcolunas na sua tabela, o SQL armazena isso como um byte compactado; 9-16 bitcolunas em 2 bytes e assim por diante.

Não parece que você vai se aproximar do limite da coluna, então isso parece bem direto. E, é claro, mantê-las bem separadas dessa maneira permite nomear as colunas para facilitar a leitura e obter todas as possibilidades de indexação que você normalmente faria (se os sinalizadores forem altamente seletivos, os índices filtrados poderão ser úteis se você puder segmentar 2008 ou mais).

Se você fizer a compactação de bits, ficará muito mais complicado fazer a indexação (provavelmente bitcolunas computadas e indexadas para representar cada posição da máscara ... mas você estará pior do que usando bitdiretamente).

Jon Seigel
fonte