Esta resposta SO altamente votada recomenda colocar imagens em tabelas separadas, mesmo que haja apenas uma relação 1:1 com outra tabela:
Se você decidir colocar suas imagens em uma tabela do SQL Server, eu recomendo usar uma tabela separada para armazenar essas imagens - não armazene a foto do funcionário na tabela do funcionário - mantenha-as em uma tabela separada. Dessa forma, a tabela Employee pode permanecer enxuta, média e muito eficiente, supondo que você nem sempre precise selecionar a foto do funcionário também como parte de suas consultas.
Por quê? Fiquei com a impressão de que o SQL Server armazena apenas um ponteiro para alguma estrutura de dados BLOB dedicada na tabela, então por que se preocupar em criar manualmente outra camada de indireção? Realmente melhora o desempenho significativamente? Se sim, por quê?
Embora eu discorde que os BLOBs devem estar apenas em outra tabela - eles não devem estar no banco de dados . Armazene um ponteiro para onde o arquivo reside no disco e, em seguida, obtenha-o do banco de dados ...
O principal problema que eles causam (para mim) é com a indexação. Usando XML com planos de consulta, porque todos os têm, vamos fazer uma tabela:
São apenas 1000 linhas, mas verificando o tamanho ...
São mais de 40 MB para apenas 1.000 linhas. Supondo que você adicione 40 MB a cada 1.000 linhas, isso pode ficar muito feio rapidamente. O que acontece quando você atinge 1 milhão de linhas? Isso é apenas cerca de 1 TB de dados, lá.
Todas as consultas que precisam usar seu índice clusterizado agora precisam ler todos esses dados BLOB na memória quando a coluna de dados BLOB é referenciada.
Você consegue pensar em maneiras melhores de usar a memória do SQL Server do que armazenar BLOBs? Porque com certeza posso.
Expandindo-o para índices não clusterizados:
Você pode projetar seus índices não clusterizados para evitar amplamente a coluna BLOB para que as consultas regulares possam evitar o índice clusterizado, mas assim que você precisar dessa coluna BLOB, precisará do índice clusterizado.
Se você adicioná-lo como uma
INCLUDED
coluna a um índice não clusterizado para evitar um cenário de pesquisa de chave, você acabará com índices não clusterizados gigantescos:Mais problemas que causam:
SELECT *
consulta, obterá todos os dados BLOB.DBCC CHECKDB
, porque eu sei que você está verificando se há corrupção, certo?Espero que isto ajude!
Qual o tamanho dessas imagens e quantas você espera ter? Embora eu concorde principalmente com @sp_BlitzErik , acho que há alguns cenários em que não há problema em fazer isso e, portanto, ajudaria ter uma imagem mais clara do que realmente está sendo solicitado aqui.
Algumas opções a considerar que aliviam a maioria dos aspectos negativos apontados por Erik são:
Ambas as opções são projetadas para ser um meio-termo entre armazenar BLOBs totalmente no SQL Server ou totalmente fora (exceto por uma coluna de string para manter o caminho). Eles permitem que os BLOBs façam parte do modelo de dados e participem de transações sem desperdiçar espaço no buffer pool (ou seja, memória). Os dados BLOB ainda estão incluídos nos backups, o que faz com que eles ocupem mais espaço e demorem mais para fazer backup erestaurar. No entanto, tenho dificuldade em ver isso como um verdadeiro negativo, pois, se for parte do aplicativo, ele precisa ser copiado de alguma forma, e ter apenas uma coluna de string contendo o caminho é completamente desconectado e permite que os arquivos BLOBs sejam obtidos excluídos sem indicação disso no banco de dados (ou seja, ponteiros inválidos / arquivos ausentes). Ele também permite que os arquivos sejam "excluídos" dentro do banco de dados, mas ainda existam no sistema de arquivos que precisarão ser limpos eventualmente (ou seja, dor de cabeça). Mas, se os arquivos forem ENORMES, talvez seja melhor deixar totalmente fora do SQL Server, exceto pela coluna de caminho.
Isso ajuda com a questão "dentro ou fora", mas não toca na questão da mesa única versus mesa múltipla. Posso dizer que, além dessa questão específica, certamente existem casos válidos para dividir tabelas em grupos de colunas com base em padrões de uso. Muitas vezes, quando se tem 50 ou mais colunas, algumas são acessadas com frequência e outras não. Algumas colunas são gravadas com frequência, enquanto outras são lidas principalmente. Separar colunas frequentemente acessadas versus raramente acessadas em várias tabelas com uma relação 1:1 é muitas vezes benéfica porque desperdiçar o espaço no Buffer Pool para dados que você provavelmente não está usando (semelhante ao por que armazenar imagens grandes em
VARBINARY(MAX)
colunas é um problema)? Você também aumenta o desempenho das colunas de acesso frequente reduzindo o tamanho da linha e, portanto, ajustando mais linhas em uma página de dados, tornando as leituras (físicas e lógicas) mais eficientes. Claro, você também introduz alguma ineficiência ao precisar duplicar o PK, e agora às vezes você precisa juntar as duas tabelas, o que também complica (mesmo que apenas um pouco) algumas consultas.Portanto, existem várias abordagens que você pode adotar, e o que é melhor depende do seu ambiente e do que você está tentando realizar.
Não tão simples. Você pode encontrar algumas boas informações aqui, qual é o tamanho do ponteiro LOB para (MAX) tipos como Varchar, Varbinary, etc? , mas o básico é:
TEXT
,NTEXT
eIMAGE
tipos de dados (por padrão): ponteiro de 16 bytesVARCHAR(MAX)
,NVARCHAR(MAX)
,VARBINARY(MAX)
(por padrão):Se os dados devem ser armazenados no SQL Server por qualquer motivo, posso pensar em alguns benefícios para armazená-los em uma tabela separada. Alguns são mais convincentes do que outros.
Colocar os dados em uma tabela separada significa que você pode armazená-los em um banco de dados separado. Isso pode ter vantagens para manutenção programada. Por exemplo, você pode executar
DBCC CHECKDB
apenas no banco de dados que contém os dados BLOB.Se você nem sempre colocar mais de 8000 bytes no BLOB, é possível que ele seja armazenado em linha para algumas linhas. Você pode não querer isso porque isso tornará as consultas que acessam dados usando o índice clusterizado, mesmo que a coluna não seja necessária para a consulta. Colocar os dados em uma tabela separada remove esse risco.
Quando armazenado fora da linha, o SQL Server usa um ponteiro de até 24 bytes para apontar para a nova página. Isso ocupa espaço e limita o número total de colunas BLOB que você pode adicionar a uma única tabela. Veja a resposta de srutzky para mais detalhes.
Um índice columnstore clusterizado não pode ser definido em uma tabela contendo uma coluna BLOB. Essa limitação foi removida será removida no SQL Server 2017.
Se você eventualmente decidir que os dados devem ser movidos para fora do SQL Server, pode ser mais fácil fazer essa alteração se os dados já estiverem em uma tabela separada.