Motivos para não armazenar arquivos no banco de dados
Infelizmente ainda é muito comum encontrar aplicações que usam o banco de dados para armazenar imagens ou arquivos binários em suas tabelas. Irei apresentar alguns motivos para que você não faça isso em seus próximos projetos e o que pode ser usado como alternativa.
Todos os testes foram realizados utilizando o PostgreSQL 14 em um container Docker em um MacBook Air M1 com 8gb de RAM
Estrutura do banco de dados usado para testes
Espaço utilizado por cada tabela (ambas com aproximadamente 400 registros)
Cada arquivo em um registro da tabela perfil possui aproximadamente 50MB.
Desempenho
Vamos comparar alguns operações básicas em ambas as tabelas.
Inserção sem arquivo
Inserção com arquivo (50MB)
Consultando 200 registros da tabela perfil_sem_arquivo obtendo todas as colunas
Consultando 200 registros da tabela perfil sem incluir a coluna que armazena o binário
Consultando 1 registro na tabela perfil incluindo a coluna com o arquivo
Consultando 10 registros incluindo a coluna com o arquivo
Removendo 394 registros com arquivo
Removendo 393 registros sem arquivo
Como podemos ver, o banco de dados performa muito melhor na tabela que não armazena um arquivo em seus registros.
Financeiro
Vamos usar o Google Cloud SQL e o Cloud Storage como exemplo para entender o custos envolvidos.
Em Julho de 2022 a instância mais barata para utilizar o Cloud SQL é a db-f1-micro em Iowa (us-central1). O custo mensal seria aproximadamente 7.67 (R 40,90), a capacidade máxima seria de apenas 3.062 GB, fora o custo do uso de rede, vCPU e memória (que como mostrei nos exemplos anteriores, ao armazenar arquivos no banco esses recursos são mais exigidos e portanto teríamos um custo maior).
Utilizando um serviço como o Cloud Storage o nosso custo cai para 0,02 a cada GB por mês + preço de uso de rede + 0,05 a cada 10.000 operações.
Com esse serviço, ainda temos a possibilidade de reduzir o valor pago utilizando classes de armazenamento mais baratas (quanto mais barato for, menor é a disponibilidade do arquivo). Dependendo do tipo da aplicação que estamos lidando, esse pode ser um recurso interessante para otimizar os custos com cloud.
Infraestrutura e CDN
Disponibilizar esses arquivos via http exige que consultas sejam realizadas no banco de dados (que no nosso exemplo anterior já consumiria quase 5 segundos da requisição) , que o servidor baixe os dados vindos do banco (gerando mais custos com consumo de rede e ocupando mais memória das instâncias do backend) e o cliente baixe esse arquivo novamente. Além de obviamente aumentar muito o tempo da nossa requisição, ainda nos leva a possíveis problemas com os load balancers que são usados pela infraestrutura da aplicação.
Ao utilizar serviços que são voltados para o armazenamento de arquivos, abrimos a possibilidade para a utilização de CDNs para o cacheamento em diferentes regiões do mundo, possibilitando um download com latência menor (super importante para o carregamento de imagens em sua aplicação).
Em resumo
Não vale a pena sacrificar a escalabilidade da sua aplicação nesse nível. Prefira armazenar apenas URLs dos arquivos em seu banco de dados e faça o uso de um bom serviço de storage. Eu particularmente gosto bastante da AWS S3 e Google Cloud Storage.
E você, já se deparou com algum problema apontado aqui em um dos seus projetos?