Armazenar uma lista de seqüências de caracteres no campo de banco de dados único é uma má idéia? Por quê?

14

Recentemente, comecei a trabalhar em algum sistema legado. As pessoas que o desenvolveram tiveram a ideia de armazenar a lista de strings em um único campo da tabela do banco de dados. Vamos dizer que é um identificador para objeto que não possui nenhuma representação nem dados no banco de dados. O alcance desses identificadores será relativamente pequeno na produção.

Por outro lado, minhas intuições e o "bom gosto do design" me dizem que ele deve ser representado em uma tabela separada (semelhante a uma tabela usada para representar relações muitos-para-muitos).

A abordagem deles é realmente ruim e seria melhor iniciar uma refatoração? Se sim, quais as más consequências que o design original pode causar no futuro? Existem princípios de design relacional que explicam essa abordagem?

Edite na resposta para comentários:

Como suponho, eles não usaram essa abordagem para resolver um problema específico, como a estrutura hierárquica de uma maneira complicada. O cenário mais provável era que eles estavam simplesmente trabalhando sob pressão de tempo e precisavam implementar novos recursos o mais rápido possível.

Estou certo de que anteriormente o campo representava um valor único. Eles implementariam o recurso para armazenar mais de um valor e tentaram evitar migrações de banco de dados.

mpasko256
fonte
6
Se é uma abordagem ruim ou não, depende de qual problema ele estava tentando resolver e de quão bem ele foi resolvido. Você pode fornecer informações mais específicas sobre isso?
21717 Robert
1
Isso só se torna um problema se você deseja consultar a lista ou gravar relatórios fora da lista. Se esses são requisitos, talvez seja necessária uma abordagem mais relacional. Se é apenas persistência, deve ser um grande negócio.
Jon Raynor
2
Mesmo que seja a coisa "certa" a fazer, eu não começaria a refatorar até que você obtenha um novo requisito que exija algo que essa estratégia não possa acomodar, como a necessidade de indexação rápida nos itens de coleção.
Graham
Atualizações para essa coluna também podem ser problemáticas.
1
@graham o novo requisito será: "ei, precisamos de uma consulta que funcione com isso". Ao construir sobre isso e não acabar logo, você torna mais difícil se livrar e fazer a coisa certa. O problema é que você ainda pode executar a maioria das tarefas com esta estratégia: SELECT * FROM Produtos AS p JOIN Contas AS ON p.account_id REGEXP '[[: <:]]' || a.account_id || '[[:>:]]' ONDE p.product_id = 123;
Pieter B

Respostas:

16

O modelo de dados não é normalizado; para ser assim, precisaria de uma mesa separada, como você diz. Nesse sentido, não é uma prática particularmente boa de modelagem de dados.

É difícil determinar se foi feito por um bom motivo ou não. É possível que a simplificação ou o desempenho da codificação possa ter sido motivador. O mais provável é que o campo contivesse originalmente um identificador, os requisitos foram alterados e os desenvolvedores não tiveram tempo ou inclinação para redimensionar.

Provavelmente mais importante é se você deve ou não se refatorar. Em circunstâncias semelhantes, não refatoraria preventivamente um caso como esse por padrão. Eu consideraria se um dos seguintes itens se aplicasse:

  1. você tem evidências de que isso causa problemas, por exemplo, nos logs de problemas herdados
  2. você sabe que estará fazendo mudanças funcionais nessa área
  3. o código que lida com os dados é particularmente complexo e difícil de raciocinar.

O que eu faria e TBH eu recomendaria isso sempre que você assumir um aplicativo legado, for iniciar um wiki (ou equivalente) e documentar casos como este. Por exemplo,

  • problemas encontrados, como o enrugamento do datamodelling
  • mudanças que você planeja implementar
  • mudanças que você não planeja implementar, mas faria se houvesse tempo
  • áreas de código difíceis de raciocinar sobre
  • áreas de código que você achou difíceis de manter.

Descobri que este é um memorando de auxílio útil para mim enquanto trabalho e / ou volto para uma base de código. Também pode ser muito útil para o seu sucessor quando eles, por sua vez, precisam começar a aprender a base de código.

Alex
fonte
10

Armazenar uma lista de seqüências de caracteres no campo de banco de dados único é uma má idéia?

Seria geralmente considerado uma violação da normalização.

No entanto, às vezes isso é usado como solução para um problema, por exemplo, na estruturação hierárquica, em que uma cadeia de caminho de comprimento variável de algum tipo representa estrutura.

Entre os problemas com uma lista de itens em uma única cadeia de caracteres podem estar:

  • na consulta, isso significa usar pesquisas de string em vez de cálculo relacional; indexar os dados pode ser problemático.
  • existe a pergunta sobre o significado da ordem das entradas na lista e é mais provável que você não possa impor nada à ordem como uma restrição no banco de dados.
  • existe a questão do caractere separador e o potencial de problema de escape / não escape de caracteres nos itens individuais.
  • existe o potencial de entradas duplicadas na mesma lista; Novamente, isso decorre de não ser possível impor restrições diretamente (embora talvez uma função de gatilho possa verificar restrições).
  • um único item ainda é uma lista, mas pode ser confundido como não, pois não podemos dizer (ou perguntar) ao banco de dados que o tipo verdadeiro é uma lista. Isso pode ser problemático se a maioria das linhas tiver apenas um item na lista, quando algumas tiverem mais de um: não há como impor o uso adequado da coluna como uma lista.
Erik Eidt
fonte
Aprecio as duas respostas, mas escolho o Alex porque ele ofereceu dicas valiosas sobre como conduzir o melhor processo de decisão sozinho.
mpasko256
3

É um antipadrão comum para fazer isso.

Seus requisitos mudam e agora você precisa de mais valores em um local em que costumava precisar apenas de um. Como um livro tem apenas um autor, certo? Quem poderia imaginar que um livro tem vários autores? Essa é uma maneira fácil de atender a essa alteração de requisitos sem precisar alterar o esquema do banco de dados.

Existem algumas desvantagens.

  • As consultas se tornam mais difíceis porque agora você tem dados de identificação combinados em um campo.
  • Você não pode mais usar "=", mas precisa usar algo como "like". O que matará o desempenho.
  • Você perde a capacidade de ingressar nesse campo.
  • Tente contar / somar, etc, não vai funcionar.
  • Atualizando, torna-se estranho.
  • Você fica com limites artificiais porque escolheu um varchar (10) para manter sua lista separada por vírgulas.
  • e mais.

Então, basicamente, por favor, não faça isso.

Basicamente, você está removendo o "relacional" no "banco de dados relacional".

Pieter B
fonte
0

Existem muitos argumentos para sermos uma péssima idéia. Eu acho que seria justo acrescentar algumas razões pelas quais seria uma boa ou pelo menos boa ideia. Não tenho certeza de quantas delas se aplicam a casos específicos, mas parece que pelo menos as observações de desempenho feitas são relevantes:

  • se o número e o comprimento das strings forem estritamente limitados, a diferença de desempenho deve ser insignificante. Pelo menos em alguns casos extremos, o desempenho será melhor, pois você não precisa da junção.
  • dependendo do uso principal do campo, este formulário pode ser mais fácil de manipular.
  • se a lista for ordenada e os dados não exigirem chaves estrangeiras, os campos da lista serão muito superiores a qualquer banco de dados relacional que forneça nesse sentido.
  • ser simples fazer o back-up no campo singular existente pode ser uma escolha prudente em sistemas onde a migração de esquema é cara. Certamente é uma dívida técnica, mas pode ser do tipo que vale a pena tomar e nunca pagar, mesmo que você precise sangrar algum interesse de vez em quando.

Ao tentar uma refatoração, é sempre uma boa idéia primeiro entender o motivo por trás das opções de design anteriores. Certifique-se de que as condições e requisitos tenham realmente mudado o suficiente para garantir o custo e o risco.

Frax
fonte