it-swarm-pt.tech

Esquema de banco de dados dinâmico

Qual é a arquitetura recomendada para fornecer armazenamento para um esquema de banco de dados lógico dinâmico?

Para esclarecer: Onde um sistema é necessário para fornecer armazenamento para um modelo cujo esquema pode ser estendido ou alterado por seus usuários uma vez em produção, quais são algumas boas tecnologias, modelos de banco de dados ou mecanismos de armazenamento que permitirão isso?

Algumas possibilidades para ilustrar:

  • Criando/alterando objetos de banco de dados via DML gerado dinamicamente
  • Criando tabelas com um grande número de colunas físicas esparsas e usando apenas as necessárias para o esquema lógico 'sobreposto'
  • Criando uma tabela 'longa e estreita' que armazena valores dinâmicos da coluna como linhas que precisam ser dinâmicas para criar um conjunto de linhas 'curto e largo' contendo todos os valores para uma entidade específica
  • Usando um sistema do tipo BigTable/SimpleDB PropertyBag

Quaisquer respostas baseadas na experiência do mundo real serão muito apreciadas

65
Fake Jim

O que você está propondo não é novo. Muitas pessoas já tentaram ... a maioria descobriu que elas perseguem a flexibilidade "infinita" e acabam tendo muito, muito menos do que isso. É o "motel barato" dos projetos de banco de dados - os dados entram, mas é quase impossível divulgá-los. Tente conceituar a escrita do código para QUALQUER tipo de restrição e você verá o que quero dizer.

O resultado final normalmente é um sistema MUITO mais difícil de depurar, manter e cheio de problemas de consistência de dados. Este não é o sempre o caso, mas, na maioria das vezes, é assim que termina. Principalmente porque o (s) programador (es) não vêem esse acidente de trem chegando e não conseguem codificar defensivamente contra ele. Além disso, muitas vezes termina o fato de que a flexibilidade "infinita" realmente não é tão necessária; é um "cheiro" muito ruim quando a equipe de desenvolvimento obtém uma especificação que diz: "Nossa, eu não tenho idéia de que tipo de dados eles colocarão aqui, então vamos colocar o que quer que seja" ... e os usuários finais estão bem ter tipos de atributos predefinidos que eles podem usar (codifique um número de telefone genérico e deixe-os criar qualquer # deles - isso é trivial em um sistema bem normalizado e mantém flexibilidade e integridade!)

Se você tem uma equipe de desenvolvimento muito boa e está intimamente ciente dos problemas que terá que superar com esse design, poderá codificar com êxito um poço sistema projetado, não terrivelmente com erros. A maior parte do tempo.

Por que começar com as probabilidades acumuladas tanto contra você?

Não acredita em mim? Google "Uma tabela de pesquisa verdadeira" ou "design de tabela única". Alguns bons resultados: http://asktom.Oracle.com/pls/asktom/f?p=100:11ieved::::P11_QUESTION_ID:10678084117056

http://thedailywtf.com/Comments/Tom_Kyte_on_The_Ultimate_Extensibility.aspx?pg=

http://www.dbazine.com/ofinterest/oi-articles/celko22

http://thedailywtf.com/Comments/The_Inner-Platform_Effect.aspx?pg=2

36
Matt Rogish

Um campo xml fortemente tipado no MSSQL funcionou para nós.

20
Bloodhound

Como alguns outros disseram, não faça isso a menos que você não tenha outra escolha. Um caso em que isso é necessário é se você estiver vendendo um produto pronto para uso que permita que os usuários registrem dados personalizados. O produto da minha empresa se enquadra nessa categoria.

Se você precisa permitir que seus clientes façam isso, aqui estão algumas dicas:
- Crie uma ferramenta administrativa robusta para executar as alterações no esquema e não permita que essas alterações sejam feitas de outra maneira.
- Torne-o um recurso administrativo; não permita que usuários normais acessem.
- Registre todos os detalhes sobre todas as alterações de esquema. Isso o ajudará a depurar problemas e também fornecerá dados CYA se um cliente fizer algo estúpido.

Se você puder fazer essas coisas com êxito (especialmente a primeira), qualquer uma das arquiteturas mencionadas funcionará. Minha preferência é alterar dinamicamente os objetos do banco de dados, pois isso permite que você aproveite os recursos de consulta do DBMS ao acessar os dados armazenados nos campos personalizados. As outras três opções exigem que você carregue grandes blocos de dados e faça a maior parte do processamento de dados no código.

16
Josh Yeager

Eu tenho um requisito semelhante e decidi usar o esquema-less MongoDB .

O MongoDB (de "humongous") é um banco de dados de código aberto, escalável, de alto desempenho, sem esquemas e orientado a documentos, escrito na linguagem de programação C++. (Wikipedia)

Luzes:

  • possui funcionalidade de consulta avançada (talvez a mais próxima dos bancos de dados SQL)
  • pronto para produção (quadrangular, sourceforge usá-lo)

Lowdarks (coisas que você precisa entender para poder usar o mongo corretamente):

9
clyfe

Eu fiz isso em um projeto real:

O banco de dados consistia em uma tabela com um campo que era uma matriz de 50. Tinha um índice 'Word' definido. Como todos os dados não foram digitados, o 'índice do Word' funcionou conforme o esperado. Os campos numéricos foram representados como caracteres e a classificação real foi feita no lado do cliente. (Ainda é possível ter vários campos de matriz para cada tipo de dados, se necessário).

O esquema de dados lógicos para tabelas lógicas foi mantido no mesmo banco de dados com a linha da tabela diferente 'type' (o primeiro elemento da matriz). Ele também suportava o controle de versão simples no estilo de copiar na gravação usando o mesmo campo 'tipo'.

Vantagens:

  1. Você pode reorganizar e adicionar/excluir suas colunas dinamicamente, sem necessidade de despejo/recarregamento do banco de dados. Quaisquer novos dados da coluna podem ser configurados para o valor inicial (virtualmente) em tempo zero.
  2. A fragmentação é mínima, uma vez que todos os registros e tabelas são do mesmo tamanho, às vezes fornece melhor desempenho.
  3. Todo o esquema da tabela é virtual. Qualquer estrutura lógica de esquema é possível (mesmo recursiva ou orientada a objetos).
  4. É bom para "escrever uma vez, ler principalmente, não excluir/marcar como excluído" (a maioria dos aplicativos da Web é assim).

Desvantagens:

  1. Indexação apenas por palavras completas, sem abreviação,
  2. Consultas complexas são possíveis, mas com uma leve degradação do desempenho.
  3. Depende se o seu sistema de banco de dados preferido suporta matrizes e índices do Word (foi implementado no PROGRESS RDBMS).
  4. O modelo relacional está apenas na mente do programador (ou seja, apenas no tempo de execução).

E agora estou pensando que o próximo passo poderia ser - implementar esse banco de dados no nível do sistema de arquivos. Isso pode ser relativamente fácil.

7
Thevs

O objetivo de ter um banco de dados relacional é manter seus dados seguros e consistentes. No momento em que você permite que os usuários alterem o esquema, a integridade dos dados se mantém ...

Se você precisar armazenar dados heterogêneos, por exemplo, como um cenário CMS, sugiro que você armazene XML validado por um XSD em uma linha. É claro que você perde o desempenho e os recursos de pesquisa fácil, mas é uma boa opção para o IMHO.

Desde 2016, esqueça o XML! Use JSON para armazenar o pacote de dados não relacionais, com uma coluna de tipo apropriado como back-end. Normalmente, você não precisa consultar por valor dentro do pacote, o que será lento, embora muitos bancos de dados SQL contemporâneos entendam JSON nativamente.

6
Sklivvz

Crie 2 bancos de dados

  • DB1 contém tabelas estáticas e representa o estado "real" dos dados.
  • O DB2 é livre para os usuários fazerem o que desejarem - eles (ou você) terão que escrever código para preencher suas tabelas de formato ímpar no DB1.
3
AJ.

Parece-me que o que você realmente deseja é algum tipo de "meta-esquema", um esquema de banco de dados capaz de descrever um esquema flexível para armazenar os dados reais. As alterações dinâmicas do esquema são delicadas e não são algo com que você queira mexer, principalmente se os usuários tiverem permissão para fazer a alteração.

Você não encontrará um banco de dados mais adequado a esta tarefa do que qualquer outro, portanto, sua melhor aposta é apenas selecionar um com base em outros critérios. Por exemplo, qual plataforma você está usando para hospedar o banco de dados? Em que idioma o aplicativo está escrito? etc

Para esclarecer o que quero dizer com "meta-esquema":

CREATE TABLE data (
    id INTEGER NOT NULL AUTO_INCREMENT,
    key VARCHAR(255),
    data TEXT,

    PRIMARY KEY (id)
);

Este é um exemplo muito simples, você provavelmente teria algo mais específico para suas necessidades (e espero que seja um pouco mais fácil de trabalhar), mas serve para ilustrar meu argumento. Você deve considerar o próprio esquema do banco de dados imutável no nível do aplicativo; quaisquer alterações estruturais devem ser refletidas nos dados (ou seja, a instanciação desse esquema).

3
Daniel Spiewak

Eu sei que os modelos indicados na pergunta são usados ​​em todos os sistemas de produção. Uma grande é usada em uma grande universidade/instituição de ensino em que trabalho. Eles usam especificamente a abordagem de tabela estreita e longa para mapear os dados coletados por muitos sistemas variados de aquisição de dados.

Além disso, o Google lançou recentemente seu protocolo interno de compartilhamento de dados, buffer de protocolo, como código aberto no site de códigos. Um sistema de banco de dados modelado nessa abordagem seria bastante interessante.

Verifique o seguinte:

Modelo de entidade-atributo-valor

Buffer do protocolo do Google

3
siculars

Abordagem EAV eu acredito que é a melhor abordagem, mas vem com um custo alto

2
kamal

A Wikipedia tem uma excelente visão geral do espaço do problema:

http://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model

2
DenNukem

Sei que é um tópico antigo, mas acho que nunca perde a realidade. Estou desenvolvendo algo assim agora. Aqui está a minha abordagem. Eu uso uma configuração de servidor com MySQL, Apache, PHP e Zend Framework 2 como estrutura de aplicativo, mas deve funcionar também com outras configurações.

Aqui está um guia de implementação simples, você pode evoluir ainda mais a partir disso.

Você precisaria implementar seu próprio interpretador de linguagem de consulta, porque o SQL efetivo seria muito complicado.

Exemplo:

select id, password from user where email_address = "[email protected]"

O layout do banco de dados físico:

Tabela 'especificações': (deve ser armazenada em cache na sua camada de acesso a dados)

  • eu não fiz
  • parent_id: int
  • nome: varchar (255)

Tabela 'itens':

  • eu não fiz
  • parent_id: int
  • spec_id: int
  • data: varchar (20000)

Conteúdo da tabela 'especificações':

  • 1, 0, 'usuário'
  • 2, 1, 'email_address'
  • 3, 1, 'senha'

Conteúdo da tabela 'itens':

A tradução do exemplo em nossa própria linguagem de consulta:

select id, password from user where email_address = "[email protected]"

para o SQL padrão ficaria assim:

select 
    parent_id, -- user id
    data -- password
from 
    items 
where 
    spec_id = 3 -- make sure this is a 'password' item
    and 
    parent_id in 
    ( -- get the 'user' item to which this 'password' item belongs
        select 
            id 
        from 
            items 
        where 
            spec_id = 1 -- make sure this is a 'user' item
            and 
            id in 
            ( -- fetch all item id's with the desired 'email_address' child item
                select 
                    parent_id -- id of the parent item of the 'email_address' item
                from 
                    items 
                where 
                    spec_id = 2 -- make sure this is a 'email_address' item
                    and
                    data = "[email protected]" -- with the desired data value
            )
    )

Você precisará ter a tabela de especificações armazenada em cache em uma matriz associativa ou hashtable ou algo semelhante para obter os spec_id's dos nomes das especificações. Caso contrário, você precisaria inserir um pouco mais de sobrecarga SQL para obter os spec_id's dos nomes, como neste trecho:

Exemplo ruim, não use isso, evite isso, armazene em cache a tabela de especificações!

select 
    parent_id, 
    data 
from 
    items 
where 
    spec_id = (select id from specs where name = "password") 
    and 
    parent_id in (
        select 
            id 
        from 
            items 
        where 
            spec_id = (select id from specs where name = "user") 
            and 
            id in (
                select 
                    parent_id 
                from 
                    items 
                where 
                    spec_id = (select id from specs where name = "email_address") 
                    and 
                    data = "[email protected]"
            )
    )

Espero que você entenda e possa determinar por si mesmo se essa abordagem é viável para você.

Apreciar! :-)

2
Oliver Konig

No passado, eu escolhi a opção C - Criando uma tabela 'longa e estreita' que armazena valores dinâmicos da coluna como linhas que precisam ser dinamizadas para criar um conjunto de linhas 'curto e amplo' contendo todos os valores para uma entidade específica.. No entanto, eu estava usando um ORM, e isso REALMENTE tornou as coisas dolorosas. Não consigo pensar em como você faria isso, digamos, LinqToSql. Eu acho que teria que criar um Hashtable para fazer referência aos campos.

@ Skliwz: Acho que ele está mais interessado em permitir que os usuários criem campos definidos pelo usuário.

0
Danimal

No wiki do c2.com, a idéia de "Dynamic Relational" foi explorada. Você NÃO precisa de um DBA: as colunas e as tabelas são criadas na gravação, a menos que você comece a adicionar restrições para agir mais como um RDBMS tradicional: à medida que o projeto amadurece, você pode "travar" gradualmente.

Conceitualmente, você pode pensar em cada linha como uma instrução XML. Por exemplo, um registro de funcionário pode ser representado como:

<employee lastname="Li" firstname="Joe" salary="120000" id="318"/>

Isso não implica que ele deve ser implementado como XML, é apenas uma conceituação útil. Se você solicitar uma coluna não existente, como "SELECT madeUpColumn ...", ela será tratada como em branco ou nula (a menos que restrições adicionais o proibam). E é possível usar SQL , embora seja necessário ter cuidado com as comparações devido ao modelo de tipo implícito. Mas, além da manipulação de tipos, os usuários de um sistema Dynamic Relational se sentiriam em casa porque podem aproveitar a maior parte do conhecimento existente sobre RDBMS. Agora, se alguém o construísse ...

0
FloverOwe

ElasticSearch. Você deve considerá-lo especialmente se estiver lidando com conjuntos de dados que podem ser particionados por data, pode usar JSON para seus dados e não está decidido a usar o SQL para recuperar os dados.

O ES infere seu esquema para quaisquer novos campos JSON enviados automaticamente, com dicas ou manualmente, que você pode definir/alterar por um comando HTTP ("mapeamentos"). Embora não seja compatível com SQL, possui ótimos recursos de pesquisa e até agregações.

0
Oren