Maneira prática de armazenar uma quantidade "razoavelmente grande" de dados que quase nunca muda?

13

Pense em termos de tabelas de pesquisa pré-calculadas ou algo assim. Em que momento faz mais sentido usar um banco de dados em vez de codificar valores no meu aplicativo? Os valores não vão mudar e são bem segregados dos desenvolvedores de manutenção. 100 valores, 1k, 10k, 100k? Estou querendo armazenar cerca de 40k valores. No momento, é uma switchdeclaração gerada por máquina (sobre a qual o VS2010 está insatisfeito).

editar:

Se alguém estiver curioso, veja como eu me aproximei disso: meus dados eram armazenáveis ​​em duas matrizes flutuantes de 100k elementos, então foi isso que fiz. Demorou cerca de 20 segundos para gerar os dados, então fiz isso uma vez e os serializei em um recurso incorporado com um BinaryFormatter. A descompactação dos dados leva cerca de 5 milissegundos na inicialização do aplicativo e supera a implementação do banco de dados que eu estava substituindo (esses valores codificados foram armazenados anteriormente) em quase 45.000x.

Bryan Boettcher
fonte

Respostas:

5

Minha sugestão é manter os dados em uma tabela de arquivo ou banco de dados. Se a velocidade não for um problema, consulte o arquivo ou o banco de dados (o banco de dados é melhor) em tempo de execução. Se a memória não for um problema, mas você desejar velocidade, carregue os dados na memória quando o programa iniciar. Em C #, você pode usar e matriz, listar ou (melhor opção) uma tabela de hash e ter um método para retornar os dados necessários em tempo de execução (por exemplo, getDataValue (string keyToValue)).

Eu recomendaria que você não use a instrução switch, pois seria muito difícil de manter e resultaria em uma grande pegada de exe.

Tabela de hash, por exemplo, http://support.microsoft.com/kb/309357

adam f
fonte
Em última análise, foi isso que fiz: verifique minha postagem atualizada.
Bryan Boettcher
1
+1 para a sugestão do banco de dados. Os bancos de dados são criados para armazenar grandes volumes de dados e permitem buscá-los rapidamente.
NoChance
Veja stackoverflow.com/questions/301371/… sobre por que é melhor usar um dicionário para isso do que uma hashtable. YMMV
Chris McKee,
6

Pessoalmente, estou bem em armazenar qualquer quantidade de dados, codificados no aplicativo, até que não seja necessário ajustá-lo para uma implantação ou hotfix específico.

No entanto, armazenar e acessar dados usando a instrução switch C # é uma prática muito ruim, pois no modelo de armazenamento de dados e acesso a dados acopla firmemente e implica apenas um método de acesso ao método (pelo parâmetro switch).

Eu preferiria armazenar dados em um Hashtable ou Dicionário e fornecer classes separadas para recuperar os dados e preencher uma vez os Dicionários de pesquisa.

Recentemente, achei bastante conveniente implementar DSL pequeno para especificar regras de negócios ( interface fluente para o SiteMap ou o método "calc" de verificação de perguntas de entrevista da calculadora de impostos) para definir as regras) e, em seguida, fornecer um objeto separado para consultar essas regras. Essa técnica se aplicaria bem ao cenário de alternância.

Um dos bons benefícios dessa decomposição é que você pode implementar várias Visualizações nos seus dados, sem tocar no blob de linhas XXXk, que define esses dados.

Valera Kolupaev
fonte
Eu estendi a resposta com alguns exemplos.
Valera Kolupaev 6/10/11
2

Uma declaração de troca de linha de 40k é um pouco questionável. Presumo que você ainda precise executar operações de consulta, certo? Você já tentou encapsular os dados? Em seguida, use o LINQ para executar operações de consulta na coleção para testar o desempenho. Obtenha momentos concretos executando testes de unidade com um timer como o StopWatch . Então, se você acha que pode funcionar. Veja se o desempenho é aceitável para os usuários.

P.Brian.Mackey
fonte
2

Eu tive um requisito como esse duas vezes. Os aplicativos foram projetados para serem independentes, sem a necessidade de configuração / acesso ao banco de dados. Nos dois casos, usei arquivos XML para armazenar os dados. No primeiro, que estava no Framework 2.0, usei as chamadas de análise XML de estilo antigo para pesquisar dados. Para o mais novo, no Framework 3.5, usei o LINQ to XML para encontrar o que precisava. Nos dois casos, o acesso aos dados foi encapsulado em classes.

jfrankcarr
fonte
1

O principal aqui é garantir que sua interface pública encapsule sua implementação - mas essa não é a sua pergunta e não há motivos para pensar que você não o fez. Além disso, é apenas uma questão de desempenho versus luto (e as diferenças de desempenho podem não valer a pena se preocupar). Como solução prática, para o problema do VS 2010, você sempre pode dividir a instrução de caso em uma hierarquia de instruções de caso - o nível superior pode chamar um dos 10 outros métodos, cada um com uma instrução de caso de 4000 casos, por exemplo. Você pode colocar cada um dos 10 em seu próprio arquivo, se necessário. Um pouco feio, mas você está gerando código de qualquer maneira.

Quanto ao número para mudar para um banco de dados, é sempre que não usar um banco de dados se tornar um problema.

psr
fonte
Aprecio o pensamento de que minha interface encapsula a implementação: certamente o faz. A funcionalidade é exposta através de um GetValuesForInputmétodo -type, e minha declaração massiva está oculta na implementação.
Bryan Boettcher
1

Você poderia usar algo como o SQL Compact. Coloque os dados em uma tabela e deixe o arquivo DB no projeto. As tabelas são mais adequadas para essa quantidade de dados do que uma instrução switch.

Morgan Herlocker
fonte
1

Eu acho que a palavra chave aqui é 'dificilmente'

Se os dados nunca mudarem - por exemplo, valores matemáticos pré-calculados, constantes de cores e similares - então, desde que o tamanho seja gerenciável para você, mantenha-o no código. Lembre-se de que, se o desempenho for um problema, as instruções case / switch serão muito lentas em comparação com outras opções.

Se os dados quase nunca mudarem - por exemplo, códigos de área telefônica, fronteiras nacionais e similares - eu provavelmente tentaria manter os dados externamente de alguma maneira. Especialmente se começar a ter mais do que uma dúzia de valores.

GrandmasterB
fonte
1
Depende de quão bom é o compilador. Uma declaração de caso no Delphi pode ser extremamente eficiente.
Loren Pechtel 6/10/11
1

Se você armazenar grandes volumes de dados em seu aplicativo, seu programa poderá carregar mais lentamente e você poderá expor o código a riscos, caso alguém possa jogar com os binários ou executáveis.

Além disso, se o programa for editado várias vezes, quem sabe, você poderá introduzir erros digitando incorretamente os números por engano ou como resultado do comando change.

Pode ser que no futuro alguém solicite a execução de consultas nos dados, digamos, alguém possa solicitar a média de uma coluna; nesse caso, você terá que alterar seu aplicativo e adicionar um método para calcular todas as consultas que o usuário fizer. com, siga todas as etapas para promover seu código para produção. Isso realmente não é bom.

Separar dados e código é uma boa prática, especialmente se os dados forem grandes.

NoChance
fonte