O professor nos disse para armazenar objetos Java serializados como blobs em vez de definir tabelas relacionais


21

Em vez de realmente definir uma tabela com os atributos corretos, meu professor nos disse que poderíamos mapear objetos para IDs como este:

id (int)  |   Serialized Object (blob)
   1               10010110110

Eu posso ver muitos problemas com isso; redundância de dados, tendo que rastrear IDs separadamente, tendo que puxar toda a tabela para a memória para procurar qualquer coisa e ** se eu quiser alterar meu modelo no código Java, não poderei mais desserializar o blob armazenado no banco de dados nesse modelo.

Ou estou sempre preso a esse modelo ou tenho que fazer outras coisas realmente feias para mudar meu modelo. ** Tudo isso parece uma má forma para mim. Estou justificado em discordar do meu professor? Existe algum benefício em fazer isso que eu não tenha pensado? Se eu estiver certo, devo dizer algo ao meu professor sobre isso? Ele estava pregando isso para toda a minha turma e até disse que construiu projetos dessa maneira. Uma segunda opinião seria ótima.

O curso se chama Design de Software .

Meu professor não disse que esse era o melhor caminho, mas ele disse que era uma alternativa legítima à definição de tabelas relacionais.

O modelo não é dinâmico de forma alguma.


Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Paul White diz GoFundMonica

Respostas:


34
  1. Não é, por si só, uma coisa ruim - de maneira alguma. Argumentar sobre "o que é melhor" sem um contexto adequado (= requisitos exatos) é um exercício de futilidade.

  2. A parte em negrito está errada. Você pode estender facilmente objetos já serializados para adicionar novos campos e obter compatibilidade binária total com os objetos mais antigos. Você também pode simplesmente criar novas classes em vez de alterar as originais.

Sua discussão com o professor deve se concentrar nos prós e contras do "relacional" versus "armazenamento de valores-chave" em diferentes cenários, e não na "amargura" abstrata. Ou você também pode discutir se o Natal é superior ao Dia de Ação de Graças.

- uma edição, depois de ler outras respostas.

Uma das outras respostas chega ao ponto de afirmar que "é difícil imaginar um caso em que os profissionais superam os contras".

Como toda a discussão deve ser sobre problemas concretos (caso contrário, não podemos nem definir "melhor" e "pior"), deixe-me dar um exemplo concreto. Está completamente inventado, mas tentei detalhar o máximo de detalhes possível.

Imagine que você tenha um site de jogos on-line, com um banco de dados que armazena estatísticas de jogadores em diferentes jogos on-line (jogados no navegador, escritos em GWT e compilados de forma cruzada em javascript). Alguns dos jogos são estratégicos, outros são de ação, outros são de plataforma. O banco de dados é relacional e armazena jogadores e histórico de jogadas e a pontuação.

Um dia, você recebe um requisito adicional: permita que os jogadores salvem o estado do jogo na nuvem, durante o jogo, para que possam reiniciar o jogo mais tarde, no mesmo ponto. Desnecessário dizer que a única razão para armazenar esse estado temporário é retornar ao jogo, o próprio estado nunca será introspectivo.

Agora você tem duas opções básicas:

  • Como os jogos são escritos em Java, você pode facilmente pegar o modelo, enviá-lo ao servidor, serializá-lo em uma linha de código e armazená-lo como um blob. A tabela será chamada de "saved_games" e terá chaves estrangeiras para o jogador e assim por diante. Do ponto de vista do banco de dados, um "jogo salvo" é um blob opaco e indivisível.

  • você pode criar um modelo relacional separado para cada um dos seus 100 jogos (serão dezenas de mesas por jogo). Somente para o pacman, por exemplo, você terá que ter uma mesa armazenando posições de todos os pellets, bônus, posições e estado atual dos fantasmas não consumidos. Se alguém, algum dia, modificar o jogo, mesmo que ligeiramente, você precisará atualizar o modelo relacional. Além disso, para cada tipo de jogo, você precisará implementar uma lógica para gravar o modelo Java no banco de dados e lê-lo novamente.

A resposta de Justin Cave diz que você deve ir com a segunda opção. Eu acho que isso seria um grande erro.

Além disso, tenho um palpite de que a percepção de Justin Cave é que o que apresentei acima é um caso "de ponta" ou "raro". Acredito que, a menos que ele possa apresentar algum tipo de dados concretos (com base em uma amostra representativa de todos os projetos de TI no mundo, não apenas, digamos, aplicativos corporativos nos EUA), considerarei essa opinião um caso clássico de projeção. viés.

Na verdade, o problema de objetos Java serializados em um banco de dados relacional é muito mais profundo do que parece. Ele toca o núcleo do 1NF, qual é o domínio de um atributo? . Se você está realmente interessado no assunto, há um ótimo artigo de CJ Date, em Data no banco de dados: Escritos 2000-2006 .


Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Paul White diz GoFundMonica

22

As pessoas podem (e fazem) entregar com êxito projetos que fazem esse tipo de coisa? Infelizmente, sim, eles fazem isso com bastante frequência.

Será esta uma boa abordagem? Não, não é. Você basicamente pega seu banco de dados relativamente caro e o transforma em um sistema de arquivos relativamente lento. Se você realmente deseja criar um sistema que salva seu estado serializando e desserializando objetos, também pode usar um sistema de arquivos em vez de usar um banco de dados.

Se você criar sistemas que armazenam dados serializando objetos no banco de dados, não fará amizade com seu DBA. Você acabará armazenando dados redundantes. Você terá dados terrivelmente inconsistentes - sempre que os dados compartilhados forem atualizados, alguns objetos terão os novos valores e outros terão os valores antigos. Você tornará impossível fazer qualquer tipo de relatório sobre os dados - tudo o que alguém quiser fazer com os dados exigirá que alguém escreva código adicional. Esse é um problema enorme, na maioria das empresas, porque eles querem fazer coisas como extrair dados de um sistema para carregar em outro sistema ou ter um sistema de relatórios que possa entregar relatórios de vários aplicativos front-end. Além disso, como você ressalta, você constantemente terá que lidar com problemas quando

Existem vantagens nessa abordagem? Eu acho que você pode argumentar que é muito fácil implementar a primeira versão do aplicativo. E permite que o desenvolvedor ignore completamente qualquer coisa relacionada à interação adequada com um banco de dados. Tenho dificuldade em imaginar muitos casos em que essas vantagens superam as inúmeras desvantagens da abordagem.

Quanto à forma como você deve lidar com esse professor em particular, essa é uma questão separada (e provavelmente fora do escopo deste fórum). Se o seu professor estiver desenvolvendo ativamente projetos no mundo real, ele provavelmente não será terrivelmente receptivo a nenhum argumento de um aluno de que sua abordagem esteja fundamentalmente errada (mesmo que a abordagem esteja realmente errada). Você pode ser melhor atendido ao fazer o projeto da maneira que o professor deseja e aprender da maneira correta de salvar dados por conta própria (ou em um curso diferente).


2
O que você disse, mais meus dois centavos. Reutilização é sobre modularidade e compartilhamento. O modelo de objeto se concentra no compartilhamento de objetos e na reutilização de código. O modelo de banco de dados se concentra no compartilhamento e reutilização de dados. Nenhum dos modelos é completamente idiota. Nenhum dos modelos é perfeição. E é muito, muito difícil conciliar os dois.
precisa

1
Eu concordo com isso, mas eu odeio ver um professor ensinar alguma coisa e dizer que é a melhor maneira sem ser confrontado com isso. E quanto a todos os outros alunos pobres da turma que entrará no mundo real pensando que esse é o caminho certo?
Kevin

Certo. Essa formulação equivale a objetos que fingem ser dados. E eles são dados, mas não são dados muito úteis.
Walter Mitty

A vantagem é quase sempre eliminada assim que você deseja lançar a v2 do seu aplicativo.
Andy

10

Há situações em que esse tipo de design é sensato, sem que você descreva o que são seus projetos e como eles são usados, é difícil dizer se isso é apropriado ou não.

Seu DBA pode te odiar se você armazenar BLOBs, mas em muitas situações a única outra alternativa é transformar as tabelas em Entity-attribute-value, o que recebe ainda mais ódio dos DBAs. A outra alternativa é usar bancos de dados não relacionais, geralmente bancos de dados baseados em objetos ou dicionários ou um banco de dados orientado a documentos, que alguns DBAs, especialmente aqueles que apenas conhecem relacional, odiariam com ainda mais paixão. No entanto, o banco de dados não relacional tem seus próprios problemas para lidar, certamente pode ser o caso de usar o banco de dados de objetos para armazenar objetos expor outros problemas que você poderia resolver facilmente em sistemas relacionais.

Existe algum benefício em fazer isso que eu não tenha pensado?

Armazenar objeto serializado significa que você pode armazenar dados sem esquema (observe que, apesar do nome, sem esquema geralmente não significa que não haja realmente nenhum esquema, mas apenas um esquema implícito). Existem muitos domínios com problemas nos quais você não pode definir o esquema antecipadamente no momento do desenvolvimento, e em que seguir o design tradicional do banco de dados relacional significa que você deve alterar o esquema do banco de dados a cada duas semanas ou terminar com uma tabela que 80% das colunas que não são utilizadas 80% do tempo ou centenas de tabelas diferentes para armazenar os mesmos dados, nenhum dos quais indica um bom design. A raiz desse problema geralmente ocorre porque você é forçado a ajustar um domínio de problema não relacional em um banco de dados relacional.

Obviamente, existem muitos projetos em que as pessoas pensam que precisam usar EAV, esquema ou armazenamento de blob que acabam causando desnecessariamente o que seria uma dor evitável. Você definitivamente deve discutir com seu professor qual é o raciocínio dele e fornecer seus próprios argumentos; ouça os argumentos e esteja preparado para acabar concordando com ele ou não, talvez ele esteja errado.


7

Eu já fiz isso antes - é uma técnica útil em certos cenários, mas depende do formato de serialização usado. Se fizer isso, certifique-se de usar um formato de serialização que permita desserializar versões mais antigas do meu modelo (por exemplo, XML).

Normalmente, eu usaria isso em cenários em que o formato dos dados resultaria em um modelo relacional complicado que não oferece vantagens (por exemplo, quando os requisitos de negócios não exigem filtragem etc.) e já estou usando um banco de dados (por outros dados relacionais). Um desses casos foi um aplicativo que tinha consultas de usuários - o modelo relacional tinha várias tabelas para armazenar coisas como condições, condições aninhadas (OR / AND etc ...), opções de classificação etc. precisávamos adicionar um novo recurso que exigisse uma alteração no banco de dados. Substituí a coisa toda por uma única tabela de consultas por um blob serializado representando todas as outras opções.

Outro caso foi um sistema que processou vários "trabalhos". Havia vários tipos diferentes de trabalhos e cada trabalho tinha parâmetros diferentes, sem requisitos de negócios para poder procurar / filtrar trabalhos com base nesses parâmetros. Armazenar isso como um banco de dados relacional exigiria pelo menos 1 nova tabela por tipo de trabalho, dificultando a adição de novos tipos de trabalho. Em vez disso, os parâmetros são armazenados como um blob no banco de dados - cada tipo de trabalho é responsável pela serialização e desserialização de seus próprios parâmetros.

Não é muito frequente que você encontre cenários como este; no entanto, de vez em quando surge uma situação como a acima, onde a serialização de dados de blob economiza muito esforço, torna seu aplicativo mais sustentável e não apresenta desvantagens reais.


6

Justin Cave está certo de que isso pode levar a dados redundantes, mas isso realmente depende de como você cria seu banco de dados.

A abordagem de serializar um objeto inteiro em um blob não é tão ultrajante quanto a maioria das pessoas pensa. De fato, para alguns aplicativos, esse pode ser o melhor design possível, como expliquei aqui: /programming//a/12644223/1121352 .

De fato, serializar um objeto leva a pelo menos dois benefícios:

1- Reduzindo a incompatibilidade de impedância : alguns tipos Java simplesmente não estão disponíveis no SQL, principalmente se você usa muitas classes e tipos personalizados, portanto, converter e voltar de objetos Java para SQL pode ser um grande aborrecimento e até levar a ambiguidades.

2- Mais flexibilidade no seu esquema . De fato, os esquemas relacionais são realmente ótimos para dados que compartilham a mesma estrutura, mas se alguns de seus objetos em uma única classe puderem ter propriedades diferentes, dependendo das condições do tempo de execução, os esquemas relacionais podem prejudicar significativamente o fluxo de trabalho.

Portanto, certamente existem benefícios para essa abordagem (pelo menos esses dois, mas certamente outros que não citei), mas é claro que o enorme custo a pagar é que você perde quase todos os benefícios dos esquemas relacionais.

No entanto, você pode obter o melhor dos dois mundos se projetar cuidadosamente seu banco de dados: ainda é possível definir um esquema relacional (por exemplo: colunas-chave exclusivas) usando os atributos exclusivos de cada objeto e armazená-lo no blob . Dessa forma, você ainda pode garantir a recuperação rápida do seu objeto, dado um identificador exclusivo definido pelos atributos do seu objeto, reduzindo também a redundância, enquanto aniquila a incompatibilidade de impedância e mantém total flexibilidade dos objetos Java.

Como observação lateral, existem algumas tentativas de alguns fabricantes de banco de dados de combinar modelos relacionais e de objetos, como o tipo de dados JSON no PostSQL e PostgreSQL, para que você possa processar JSON diretamente como qualquer coluna relacional e também SQL3 e OQL (Object Query Language) para adicionar suporte a objetos (limitados) no SQL.

No final, tudo isso é uma questão de design e compromisso entre o modelo relacional e o modelo de objeto.

/ EDITAR depois de ler os comentários: é claro, se seus dados devem ser pesquisáveis ​​("consultáveis"), você NÃO deve armazenar seus dados como um blob. Porém, se algumas partes dos seus dados não pretendem ser pesquisáveis , mas algum tipo de metadado, o armazenamento dessa parte como um objeto dentro de um blob pode ser uma boa solução, especialmente se esses metadados tiverem uma estrutura flexível e pode mudar de objeto para objeto.


5

Vamos dar um exemplo prático de quando eu fiz isso no passado.

Temos um banco de dados que contém todos os dados para um aplicativo multiusuário; o banco de dados também possui uma tabela de usuários com seus direitos de acesso. Todos esses dados são normalizados conforme o esperado.

Em seguida, solicitamos que o aplicativo se lembre de quais janelas um usuário abriu e o que estava fazendo, para que ele possa restaurar o estado quando o usuário começar a trabalhar na manhã seguinte.

  • Em primeiro lugar, se isso às vezes falha, não é impertinente

    • Por exemplo, se a primeira vez que alguém usa uma nova versão do aplicativo, esquece as janelas que estavam abertas, e daí…
  • Portanto, há um retorno de 100% se os objetos mudarem e, portanto, não podemos ler o bloco.

  • Já temos um banco de dados centralizado com controle de acesso, backup, etc.
  • O custo de armazenamento dos dados em arquivos é alto, pois os arquivos deverão ser colocados em algum tipo de servidor de arquivos ao qual todas as máquinas dos usuários tenham acesso ou uma API precisará ser gravada para ler esses arquivos.

Em outra ocasião , tínhamos um aplicativo que fazia muitos cálculos de longa duração e os usuários desejavam poder reiniciar os cálculos a partir do último ponto de conhecimento, se houvesse um corte de energia, etc. Não há como uma versão diferente do era esperado que os aplicativos reiniciassem os cálculos e, como havia muitos objetos que precisavam ser salvos, normalizar os dados teria sido caro.

Como o banco de dados já existe e está sendo usado para os dados normalizados do aplicativo, bem definidos, e não há motivo real para não usá-lo para armazenar os blogs, adotamos a opção rápida e sensível.


4

Um fator muito importante: a serialização Java (que é ativada pela implementação Serializable) é um formato muito ruim por si só; portanto, você realmente não deve usá-lo para armazenamento permanente de objetos.

As desvantagens da serialização java incluem:

  • Os dados não são realmente legíveis de outros idiomas.
  • Não é muito fácil manter a compatibilidade direta de objetos serializados, ou seja: se você adicionar (ou remover) campos à classe, não será tão fácil ler objetos criados pela versão anterior da classe.
  • Não é tão rápido (mas sua milhagem pode variar)

Portanto, se você usar qualquer outro formato de serialização, obterá um bom armazenamento de valor-chave; se usar a serialização java, ficará confuso.


Os fatos na resposta são simplesmente falsos: 1) o formato é coberto por uma especificação exaustiva; 2) adicionar campos não é um problema, o formato é muito flexível; 3) a velocidade depende dos dados reais, mas é comparável (às vezes mais rápida, às vezes mais lenta) a formatos como JSON ou XML. Basicamente, toda a resposta está errada, exceto uma linha: "os dados não são realmente legíveis de outros idiomas".
Fdreger

1
Além do 1)que estava errado, o restante da resposta é válido para IMO. Se você deseja ter controle sobre a desserialização - que é necessária quando você adiciona / exclui campos (e especialmente quando possui campos finais), as interfaces parecem desajeitadas e é necessário substituir mais métodos do que é necessário readObjecte readReplace(para campos finais).
jb.

Você está errado, adicionar e remover campos não requer a gravação de nenhum método. Quanto aos campos finais - sua resposta original não os menciona e, se o fizer, seria irrelevante (o problema seria comum para todos os outros formatos). Finalmente, dizer "Não é tão rápido (mas sua milhagem pode variar)" simplesmente não significa nada. Você tem apenas um fato certo: o de outras línguas. Essa é uma base muito fraca para chamar algo de "uma bagunça".
Fdreger

1
A adição de campos não exige que você escreva nenhum método, mas se quiser influenciar como eles são desserializados, será necessário especificar esse comportamento. Vou tentar desenterrar algumas referências a problemas com a desserialização do esquema de objetos em evolução.
jb.

3

Este é um tópico interessante com algumas respostas bem pensadas. Não estando familiarizado com todas as implicações de armazenar e recuperar objetos serializados, acho que seria interessante fornecer a resposta que eu poderia dar a uma equipe de DBA ou equipe de desenvolvimento:

A chave é atender aos requisitos atuais e futuros e manter a solução o mais simples possível, para minimizar o trabalho futuro de suporte. Os requisitos funcionais e não funcionais (por exemplo, infraestrutura e banco de dados) devem ser atendidos. Lembre-se da regra 80/20. Entenda a importância do aplicativo para os negócios e que esforço de desenvolvimento é apropriado.

Não fique preso no espaço, velocidade e memória do banco de dados, se não houver problemas.

Se um DBMS estiver na sua lista aprovada, você poderá usá-lo em uma solução, desde que os custos sejam adequados. Não há problema em usar um Banco de Dados Relacional para armazenar Blobs simples, especialmente se isso simplificar as coisas.

Se a solução deve ser um protótipo ou uma versão / estágio inicial, há ainda mais estresse em manter as coisas simples. Você sempre pode estender o esquema de dados posteriormente, desde que planeje.

Lembre-se de que os bancos de dados relacionais não impõem integridade ou consistência, a menos que o esquema cubra uma área de negócios independente e as regras de negócios sejam rigorosas. (por exemplo, a solução para a questão de objeto serializado pode considerar um repositório de estilo de dicionário / ontologia para impor regras).

Vale considerar que todos os bancos de dados relacionais não usam esquemas de bancos de dados relacionais puros (por exemplo, estrelas, espaciais, não relacionais ...), também os aplicativos podem usar bancos de dados relacionais como lojas não relacionais, como na pergunta. Muitos bancos de dados de negócios principais funcionam dessa maneira.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.