Vou executar várias simulações usando um aplicativo que escrevi em um futuro próximo e estou tendo problemas para projetar meu banco de dados com base nisso.
Veja como funciona. Cada simulação possui 6 parâmetros que podem variar, e cada parâmetro possui ~10 opções. Portanto, temos cerca de 1 milhão de permutações disso para armazenar de alguma forma no banco de dados. A maneira mais simples que posso pensar é ter uma coluna para cada parâmetro, com uma coluna adicional para minha chave primária (ExperimentID). Eu poderia acessar os parâmetros de um determinado experimento diretamente fazendo um simples
SELECT * FROM Parameters WHERE ExperimentID = (givenID)
Cada parâmetro será armazenado no banco de dados como um int, que será interpretado pelo meu aplicativo como os parâmetros necessários em tempo de execução.
Uma maneira mais complexa, mas acho que mais rápida, de fazer isso é aproveitar a velocidade do deslocamento binário. Em vez de armazenar os parâmetros diretamente, eu armazenaria as informações sobre cada parâmetro em 4 bits de um unsigned int. Na verdade, não sei como os ints são armazenados (em termos binários) no banco de dados, então esse é o principal obstáculo.
Algum conselho sobre o que fazer nesta situação? Além disso, ainda não tenho essas colunas, portanto, se decidisse pela primeira opção, como preencheria uma tabela com todas as permutações de um conjunto de parâmetros?
Por que você acha que obscurecer dados reais em um campo mascarado por bits será mais rápido? Você está falando apenas de 1 milhão de linhas e 24 bytes por linha. Isso realmente não é muito, especialmente porque você está apenas fazendo operações singleton / seek.
Uma otimização melhor seria usar
TINYINT
campos (intervalo de 0 - 255 ;byte
em .NET). UsandoTINYINT
em vez deINT
(e assumindo umFILLFACTOR
** de 100) resultaria em:INT
camposAs principais eficiências obtidas aqui são:
tempo de pesquisa inicial mais rápido para 2244 registros. Como assim? Com 1 milhão de linhas, 287 linhas por página de dados de 8k equivalem a 3484 páginas, enquanto 806 linhas por página de dados de 8k equivalem a apenas 1240 páginas. Depois que uma página é lida para obter os valores da primeira linha, ela deve permanecer no buffer pool (ou seja, memória) para pesquisas subsequentes (ou seja, as outras linhas na mesma página de dados). Mais linhas por página significa menos páginas para ler do disco--2244 páginas a menos neste caso. Mas uma vez que todas as páginas estão no buffer pool, as pesquisas devem ter a mesma velocidade, sejam 806 linhas ou 287 linhas por página. Portanto, 2.244 operações de pesquisa em 1 milhão são um pouco mais rápidas. Certamente nada mal, pois não houve custo associado a essa otimização, mas apenas queria que fosse colocado em perspectiva.
menos memória necessária para manter a tabela inteira na memória. isso fará com que seja mais provável que permaneça na memória.
Por fim, é definitivamente possível espremer esses dados em uma representação ainda menor. Mas neste ponto são 10 bytes por linha sem nenhuma complicação adicionada ao processamento/codificação e todos os valores são legíveis por humanos. Não há muito espaço para ir abaixo de 10 bytes por linha, mas mesmo que caia para 7 bytes por linha (INT IDENTIDADE + 3 bytes para Parâmetros, que deve ser o mínimo necessário para lidar com esses intervalos), estou não tenho certeza se a complexidade adicional valeria a pena (ou seja, deseconomias de escala).
E você pode preenchê-lo usando o seguinte (que assume dois parâmetros de 0 - 4, dois parâmetros de 0 - 7 e dois parâmetros de 0 - 9 ; com base nos comentários da pergunta):
A consulta acima gera apenas 160 mil permutações, não 1 milhão, novamente com base nos comentários da Questão. Mas deve ser bastante fácil descobrir como ajustá-lo para diferentes intervalos de valores para qualquer combinação dos seis parâmetros.
** FILLFACTOR: As linhas são armazenadas em páginas de dados com aproximadamente 8060 bytes. Linhas menores = mais linhas que cabem nesse contêiner de tamanho fixo.
FILLFACTOR
é quanto espaço reservar (ao criar/reconstruir um índice) para novas linhas ou atualizações que ocupam mais espaço devido a campos de comprimento variável que requerem mais bytes para a nova versão da linha. Um valor de 100 significa que não há espaço reservado, que 100% do 8060 deve ser ocupado pelas linhas atuais. Nesse cenário, há apenas campos de comprimento fixo e nenhuma inserção fora da sequência.Gosto da ideia de armazenar os parâmetros de teste em uma única
INT
coluna. Com isso em mente, criei o seguinte test-bed que pode ajudar a explicar como criar a tabela com os parâmetros de teste e como extrair esses valores posteriormente.Primeiro, criamos 3 tabelas que usaremos para construir os conjuntos 0-4, 0-7 e 0-9.
Aqui, preenchemos as tabelas:
Esta é a tabela que usaremos para armazenar os
INT
valores de deslocamento de bits combinando os 6 conjuntos de números:E aqui preenchemos essa tabela das 3 tabelas temporárias acima:
Esta próxima parte mostra como extrair os números em 6 conjuntos diferentes de uma única
INT
coluna:Como existem apenas 160.000 linhas (o número de permutações que você sugere), esta tabela requer apenas 2,6 MB de espaço de armazenamento (aproximadamente 330 páginas de dados), incluindo a
IDENTITY
coluna, que pode ou não ser necessária.Uma amostra dos resultados
select
acima são: