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 => value
mapeamentos, 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
Tabela
requests
(id, timestamp, uri)
por exemplo(1, 149382220, '/')
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
SQL
não é específico o suficiente. Você foi solicitado duas vezes. Eu sou o terceirohstore
oujson
tipos de dados (oujsonb
se / quando eles "upgrade" para 9.4).Respostas:
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.
fonte
hstore
oujson
. Nos próximos 9,4jsonb
seria a minha recomendação.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.
fonte
BLOB
é usado, o que significa OBject longo binário . Eu preferiria usar umCLOB
(Character Long OBject) ou algo parecidotext
no PostgreSQL, pois estamos falando de caracteres e não de dados binários.