Socoorro! JSON no banco de dados?

Fala devs,

estou em contato com um sistema onde os dados de retorno de uma api são armazenados dentro do db tem muitos json passando de 30MB de tamanho. Para contexto estamos falando de um banco de dados PostgreSQL com TB (Terabytes).

Dos grandes problemas as quedas do server e lentidão são normais.

Index já não são uma opção.

Na nossa área sempre tem um "depende" e eu ja usei um campo de texto para armazenar um json, (nao me orgulho disso) mas era o recurso disponível, tmb era outro contexto, totalmente diferente, e se tratava de um texto com no maximo 512 caracteres.

No contexto atual tem json de 120 MILHÕES de caracteres, não consigo me conformar com isso.

Então me ajudem a entender por favor.....

Isso é comum por ai? Tem vantagens técnicas nessa pratica? existe algum ganho válido? ou so estamos trocando o custo de lugar (storage x custo de processamento)? Existe algum video no tiktaka que apresenta uma solucão magica? (kkkk)

Na minha visão.. binarios deveriam ir para um storage (s3, azure blob, etc), estou equivocado?

me ajudem por favooooor...

Bem... depende.

Pode ter ganho, pode ser válido, mas não temos como saber. Só daria para dizer vendo o todo, cada detalhe, se aprofundando em tudo.

A chance maior é de isso ser um completo erro, mas é só um feeling que eu tenho vendo isso, eu não aposto nisso.

Só perguntando para quem fez quais foram as motivações. Se não tem como, e não consegue enxergar por conta própria, provavelmente ficará sem saber.

Esse tipo de coisa provavelmente foi feito porque quem só queria dar a solução. Queria uma solução "mágica". E por querer soluções mágicas que saem essas coisas. É muito comum isso ser fruto de falta de comprometimento com o que estava fazendo. Mas poderia ter uma justificativa boa.

O fato de não ter uma informação que demonstre porque é assim já é um indício que algo foi feito "nas coxas".

E para resolver precisaria de uma avaliação minusciosa de quem entende de banco de dados. Uma das soluções é abandonador tudo isso e apenas criar uma outra solução boa apreveitando os dados. Mas se for feito com o "mesmo capricho" desse, será só um novo problema.

Faz sentido para você?

Espero ter ajudado.


Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente. Para saber quando, me segue nas suas plataformas preferidas. Quase não as uso, não terá infindas notificações (links aqui).

Obrigado pela sua resposta @maniero! Sim, sua resposta faz total sentido! Compartilhamos do mesmo feeling sobre a "proposta" desta solução, porém os idealizadores não são lá as pessoas mais abertas para este questionamento. Mas acredito que sua intuição sobre "...foi feito porque quem só queria dar a solução..." parece bem crível pelo que conheço do cenário. Se tiver disponibilide de exemplificar um cenário onde podem haver ganhos ficarei extremamente grato (apenas para eu ter uma idéia) pois sinceramente tenho uma opnião contrária sobre este uso, e tento evitar com todas as forças.
Não consigo pensar em nada que sirva para este caso. Precisa saber bem o objetivo. E precisaria ter mais dados para avaliar. Eu falei mais no sentido, sem dados tudo pode acontecer. Talvez seja um caso para usar um modelo de documento e não um relacional. Eu costumo falar sempre que o modelo de documento não é para ser usado na maioria dos cenários, mas esse tem jeito de ser um dos que deveria. Mas pode ter algo que eu não sei. Pode ser que só não deveria ter esses JSON. Seria estranho alguém optar por isso, mas já vi de tudo. Vi algumas vezes o banco de dados inteiro estar em uma tabela. Então as pessoas fazem maluquices extremas com muito mais frequência do que deveria. As pessoas se importam só que funcione. Isso não é engenharia. Por isso sugeri que a solução poderia ser pegar os JSON e transformar em modelo relacional. Dá mais trabalho, mas é o correto. Pode ter outros problemas que nem sabemos. Embora o JSON pareça atrapalhar todo o resto. Teria que ser pensado para resolver outras questões. Eu cansei de ver coisas assim, até ganhei a vida consertando coisas desse tipo, e o primeiro foi na faculdade. Não sei como deram diploma para as pessoas que tinha feito o sistema que eu tive que arrumar. É preciso levar a profissão mais a sério. E se eu te falar que a maioria (não estou exagerando) do que eu pego que alguém fez está tudo errado. Em boa parte dos casos não é um grande problema, porque mais ou menos funciona, mesmo que crie problemas de manutenção e ou algum problema menor que não parece nada errado. E meus amigos falam a mesma coisa. E aí tenho que repetir, a pessoa precisa de formação completa, não basta aprender um detalhe ou outro, porque fica um problema estrutural. A pessoa sabe do tijolo do meio da parede, mas mas não tem o resto da parede, não tem alicerce, e a casa não para em pé.

De forma geral, e sem saber dos requisitos do sistema, eu costumo dizer que depende.

Mas neste caso específico, não consigo imaginar uma situação em que faça sentido ter um JSON com milhões de caracteres no banco.

Outro ponto confuso é que primeiro vc diz que são caracteres, mas depois menciona "binários". O que exatamente tem nesse JSON? Precisa estar tudo junto mesmo? Não tem como separar as informações em várias tabelas e só juntar na hora que precisa do JSON final?

Enfim, sem mais informações fica difícil opinar algo. Mas à primeira vista parece tudo muito estranho, e provavelmente não foi feito da melhor forma.

Vocês estão salvando o que em json para ter 120m de caracteres kkk e quando tempo leva para essa API responder com um retorno de 30MB.

E sim é recomedado guardar dados binarios em um cloud e não diretamente na consulta. Depois que guardar em um cloud, ai sim usar o arquivo, retornando do banco de dados a URL onde está hospedado o arquivo

Amigo... nem eu sei.. essa porra não abre... kkkkkkkkkkkkkkkkkkkkkkkk.. se da um select pelo dbeaver o java crasha com estouro de buffer do java. Se o usuário do sistema tenta vizualizar na web, o navegador trava... kkk... pra eu ver isso tive que abrir no python pra ver um trecho do arquivo. Sobre o tempo da API... começa com no minimo 15 segundos. pela sua resposta sobre a recomendação de se armazenar os binários fora da consulta, consegue pensar em um exemplo onde armazenar o binário no bd seria uma vantagem? Obrigado pela sua resposta.
Nunca ouvi falar em nenhuma vantagem em colocar binário no banco. Salvar dados em json já é outra coisa. O PostgreSQl tem suporte a isso. Eu uso para, por exemplo, gerar o histórico de um pedido. O endereço do cliente existe lá na tabela de endereços mas eu coloco um json com a mesma informação na tabela de pedido pra manter o dado intacto mesmo que o usuário altere o endereço. Só para informações que não serão usadas para buscar, apenas para manter a informação já processada.
Json não é necessariamente um dado binário, é uma string, padronizada para organização de dados de maneira estruturada. Acho que a discussão aqui não chegará a lugar algum, pois o que temos é um cenário onde nem mesmo ler os dados o amigo acima conseguiu, sem sabermos o que é armazenado dessa não podemos sugerir solução A ou B. Talvez o foco seja encontrar uma forma de ler o conteúdo, uma delas seria, aí sim, gerar um arquivo por meio de um dump apenas da tabela onde esse json's são aramzenados. `pg_dump -U –inserts -t > dump.sql`

Como não sei a natureza desses dados fica difícil dizer se faz sentido ou não. Porém, há uma abordagem que já utilizei que me ajudou a manter o banco saudável. O json, Eu salvava em um banco de chave-valor (era um Redis) e a chave, Eu enviava para o banco relacional para criar uma referência com meus dados. No seu caso, tu ainda poderia manter eles adicionalmente em um S3, para garantir maior durabilidade. Porém, fica a ressalva: Eu não tinha um cenário com objetos tão grandes, e talvez um banco de chave-valor sofra um pouco no seu caso.

obrigado @josefilho! se eu tivesse planejado o sistema e houvesse a necessidade de avaliar chaves dos objetos, eu seguiria uma abordagem próxima a sua, mas não se usa nenhuma chave desse objeto, nunca. Na sua opnião ainda é válido armazenar isso no banco?
Eu diria que vale a pena pensar em mover esse objetos (sem perder a referência com os dados com os quais eles se relacionam) para um storage com menor custo (um S3 por exemplo). Porém, é necessário avaliar o impacto disso. Tudo é um tradeoff. Essa é a hora de agir como um Senior. Se organize com o time, crie uma agenda para implementar uma prova de conceito (tiro curto, entre 2 à 3 semanas), e execute benchmarks. Talvez tu chegue em uma resposta melhor do que só o plano das ideias. Te garanto que se a abordagem se provar melhor, a carga do banco será menor, mais barata e vai reduzir a instabilidade da base de vocês. Bom trabalho ;)

Postgres tem API para Json. Acho que ela da seu jeito para otimizar as coisas! https://andrewrosario.medium.com/utilizando-json-no-postgresql-com-jsonb-data-types-3c4d10dd4ea3

Essa API nasce para competir com bancos não relacionais! Que usam Json ou algo parecido. E já é bem usada e comum. Agora o jeito que tudo esta salvo que diz como isso vai ficar lento ou rápido!

Obrigado por sua resposta @uriel! Ja tinha visto essa API antes e quando vi sobre essa fiquei impressionado, mas você acha ela válida em um cenário onde o json é apenas repassado, sem nenhum tratamento?
Ai não sei te dizer, teria que ler melhor a documentação pra entender bem o caso! Eu não conheço bem a API!

O Postgres tem funções de JSON, não sei qual o framework/orm que vocês estão usando, mas eu sei que no django tinha um JSONField que dava pra inclusive pegar o dado dentro do json usando as queries do ORM, tipo como um não relacional.

Mas no seu caso aí, tem que ver se os dados seguem um padrão que possa ser convertido em tabelas, senão acho que o jeito é usar um não relacional ou até um redis da vida, se não tiver necessidade de armazenar por muito tempo.

Cara, isso é pratica relativamente normal, e é possivel até pesquisar... Mas é certamente algo que a gente nunca vai ver como padrão.

Sugestão seria armazenar num s3 se não precisar fazer queries.

Algumas perguntas para refinar a resposta:

  1. Você está fazendo queries em cima desse JSON ou apenas armazenando e lendo de acordo com outros campos da tabela?
  2. O conteúdo integral desse JSON é realmente necessário, ou dá pra fazer uma sanitização, removendo partes inúteis?
  3. Se não

Não sei a estrutura do Banco de Dados e também os dados armazenados, mas falarei dos casos em que eu gosto de usar jsonb em uma tabela:

  1. Quando eu preciso salvar dados auxilares de um registro que podem seguir um schema definido ou não e que eu não necessite realizar comsultas dentro deste campo, ou seja, são dados exclusivamente para visualização ou o processamento deles podem ser feitos no backend;
  2. Quando eu preciso fazer uma tabela de histórico dos dados, exemplo:
Tabela_Referencia Registro_PK Registro_Antigo Novo_Registro Acao Data_Acao
usuario 1 {"nome": "Fulano"} {"nome": "Fulano de Tal"} update 2023-07-02

No exemplo acima, temos uma tabela que mostra o histórico dos dados de todas as tabelas para fins de auditoria, o registro exemplificado contém uma atualização do campo nome do registro 1 da tabela de usuários.

Como eu mostro esses dados? Crio uma view materializada devidamente indexada com atualização periódica concurrently e faço a query na própria view ou obrigo o usuário administrador à escolher um período, tabela de referência e um pk (mas é apresentado de forma amigável no front).

  1. Nunca armazene binário no Banco de Dados, nem que seja imagens de 30 kb, a boa prática é você salvar o arquivo em uma pasta no servidor ou utilizar um serviço de cloud storage, registrar o caminho relativo do arquivo (sem vazar essa informação para o front) ou a URL completa quando armazenado em um serviço externo.

Estes são os casos de uso que eu tenho experiência e consegui lembrar agora.

Você vai ler muitos dependes aqui, portanto vou traçar qbaixo um racional para resover as constantes quedas que tens hoje, ok?

A empresa precisa consultar todos estes TB de dados? Normalmente as empresas não precisam de mais de 3 anos de dados em seus bancos, valide com sua organização qual é janela maxima de consulta destes dados e... crie um backup da base e coloque num S3, apague os dados desnecessários. crie uma rotina automatizada para fazer este backup e expurgo de dados mensal ou trimestral. Sobre a coluna no banco com JSON, a pergunta é voce precisa mesmo disso dentro do banco? com que frequência voce consulta este dado? O que fazer com ele, tem umas ideias boas boas aqui como colocar o arquivo no s3 e guardar o caminho,acho deveras interessante, principalmente se você não tem necessidade de fazer nenhum tipo de consulta dentro deste json. Em caso de consultas pode usar o próprio postgress para te auxiliar, pode usar tabelas de extensão para guardar este dado e não deixar sua tabela principal pesada ou ate considerar o uso do mongobd para guardar estes json. Lembre-se de programar um expurgo para estes dados senao tu vai gastar muito com o tempo. Boa sorte

Se você não vai fazer query nesses dados (se está armazenando apenas como um log ou para permitir o download desse conteúdo no futuro), eu sugeriria ao time de armazenar em storage mesmo.

Acredito que a única vantagem que pode ter sido pensado quando criaram a coluna, é que pode ser mais prático manter o json (criar, atualizar e excluir) sem a necessidade de um código extra, e também bem provável por falta de conhecimento de outras abordagens.

Cara, eu criaria um esquema pra organizar e salvar no S3, e na tabela salvaria apenas o caminho do S3 em questão. Me parece a forma mais interessante.

Cria alguma coisa pra fazer essa migração, pode ser uma cron que faz parcelado.