Alternativa ao EAV para campos dinâmicos em um data warehouse de esquema em estrela

13

Preciso oferecer suporte a campos e valores dinâmicos em um grande datawarehouse para armazenar o log de solicitações de API. Meu caso de usuário é que preciso armazenar todas as cadeias de consulta de solicitações de API e poder executar consultas com elas no futuro (para que não seja apenas armazenamento, então eu não posso usar blob para eles)

por exemplo http://example.com/?action=test&foo=abc&bar=def...

Eu preciso armazenar todos os field => valuemapeamentos, ou seja (action => test), (foo => abc), (bar => def), e como o campo é tão dinâmico, a única solução que encontrei é usar o Entity-Attribute-Value, no entanto, as pessoas continuam dizendo que é um projeto muito ruim.

Portanto, considere meu caso de uso acima, qual seria uma alternativa adequada ao EAV?

Meu esquema atual usando KAV

  1. Tabela requests
    (id, timestamp, uri)
    por exemplo(1, 149382220, '/')

  2. Tabela params
    (request_id, key, value)
    por exemplo(1, 'action', 'test'), (1, 'foo', 'abc'), (1, 'bar', 'def')

Alguma sugestão?

Atualização: Executamos o armazém no AWS RedShift

Howard
fonte
2
O que há de errado em tentar o que você está sugerindo em um banco de dados dev? Além disso, você está falando sobre o SQL Server? A tag sql é bastante ampla.
Max Vernon
Atualizei a minha pergunta
Howard
1
Qual DBMS você está usando? Alguns têm recursos de indexação de texto muito bons, então eu não descartaria o uso de um campo "texto longo" para armazenar solicitações. Dito isto, não teria problemas em usar o modelo que você propõe. Embora o EAV, em sentido estrito, esteja sendo usado apenas para esse fim muito específico. Novamente, tendo dito isso, que tipo de consulta você precisa fazer? Tente escrever essas consultas nesse modelo para ver se funciona para você.
Colin 't Hart
1
Qual RDBMS você está usando? SQLnão é específico o suficiente. Você foi solicitado duas vezes. Eu sou o terceiro
Erwin Brandstetter
2
Desde RedShift é baseado em PostgreSQL, gostaria de tentar usar o hstoreou jsontipos de dados (ou jsonbse / quando eles "upgrade" para 9.4).
Colin 'Hart

Respostas:

11

Posso pensar em três soluções - EAV, XML e Sparse Columns. Este último é específico do fornecedor e pode não ser útil para você.

Qualquer que seja o método escolhido, considere armazenar os dados da solicitação original em um formato bruto, em uma tabela ou arquivo simples. Isso facilitará a tentativa de novas maneiras de armazenar os dados, permitirá que você recarregue os dados se descobrir um erro na maneira como está analisando suas solicitações e oferecerá oportunidades para analisar as solicitações da API usando processamento em lote ou "big data" ferramentas se você achar que seu armazém de dados não é capaz de lidar com os dados com eficiência.

Considerações sobre EAV

O EAV / KVS, como você descreveu acima, provavelmente será a implementação mais direta.

Infelizmente, também será muito caro - para obter qualquer tipo de consulta eficiente sobre as chaves usadas com frequência, você precisará ter índices na coluna chave, que podem ficar muito fragmentados. Consultar chaves específicas seria extremamente caro.

Você pode reduzir o custo da indexação ou das varreduras de índice dando suporte ao seu armazenamento EAV com visualizações materializadas (muitos fornecedores suportam isso) para consultar chaves ou valores de seu interesse.

XML

A maioria dos sistemas de banco de dados corporativos oferece manipulação XML muito madura, incluindo validação, indexação e consultas sofisticadas.

Carregar a solicitação da API no banco de dados como XML forneceria uma tupla por solicitação, que logicamente pode ser um pouco mais agradável para você do que ter um número desconhecido de linhas em uma tabela EAV.

Se isso é eficiente, depende muito do seu fornecedor de RDBMS e de sua implementação.

A maior desvantagem é que essa é provavelmente a única maneira de gerenciar dados mais complicados do que a manipulação de strings da solicitação original!

Colunas esparsas / mesas tradicionais

É possível que você possa carregar seus dados em uma estrutura de tabela tradicional, com uma coluna por chave.

O recurso Colunas esparsas do SQL Server é uma ótima alternativa para um armazenamento EAV. Uma tabela com colunas esparsas se comporta da mesma forma que uma tabela normal, exceto que ela pode ter até 30.000 colunas, e valores NULL em colunas esparsas não consomem espaço na tabela.

Combiná-los com índices filtrados (outro recurso específico do SQL Server) pode fornecer uma alternativa extremamente eficiente a um armazenamento EAV se você estiver frequentemente consultando algumas colunas e / ou valores específicos.

O uso de uma tabela tradicional com outros fornecedores pode ser viável - a IBM suporta mais de 700 colunas por tabela e o Oracle cerca de 1000, e recursos como compactação ou tratamento da Oracle de nulos à direita podem significar que você pode armazenar seus dados de API com bastante eficiência.

A desvantagem óbvia dessa abordagem é que, ao adicionar novas chaves à sua API, você precisará ajustar seu esquema de acordo.

Nathan Jolly
fonte
2
No PostgreSQL, eu não recomendaria XML, mas sim hstoreou json. Nos próximos 9,4 jsonbseria a minha recomendação.
Colin 'Hart
Eu realmente gosto desta resposta com os prós e contras de cada uma. Muito informativo - eu definitivamente aprecio as informações sobre as colunas esparsas. Eu gostaria de um exemplo de EAV usando a abordagem de coluna esparsa.
StixO 15/01
9

O EAV não é um design ruim, por si só, é simplesmente um design que requer uma quantidade razoável de premeditação e pode ser trabalhado com problemas de desempenho à medida que a quantidade de dados aumenta. Pode ser que, para o seu sistema, funcione bem.

Quando projetei um sistema para armazenar seqüências de caracteres de consulta, eu não tinha idéia antecipada de quais campos eu estaria interessado. Criei uma tabela para armazenar a sequência de caracteres de consulta no formato binário serializado e construí um sistema que me permite dividir a consulta amarrar as peças componentes uma vez que eu conhecia as peças que me interessavam. A partir daí, criei um conjunto de tabelas; um para os conjuntos de dados normalmente contidos na cadeia de consulta.

Por exemplo, eu finalmente tive uma tabela para dados de referência, uma para dados de solicitação de destino e outra para itens relacionados ao usuário, como a consulta de pesquisa inserida.

Eu encontrei a capacidade de armazenar toda a cadeia de caracteres de consulta em uma única tabela como um blob, enquanto fornecia a capacidade de dividir esse blob no futuro, atendendo minhas necessidades muito bem.

Max Vernon
fonte
1
Tanto na pergunta quanto na resposta, o termo BLOBé usado, o que significa OBject longo binário . Eu preferiria usar um CLOB(Character Long OBject) ou algo parecido textno PostgreSQL, pois estamos falando de caracteres e não de dados binários.
Colin 'Hart
2
Eu usei um campo binário desde que realmente serializei o objeto inteiro da sessão e armazenei tudo no banco de dados.
Max Mayon