Embora eu discorde que os BLOBs devam estar em outra tabela - eles não devem estar no banco de dados . Armazene um ponteiro para onde o arquivo está no disco e obtenha-o no banco de dados ...
O principal problema que eles causam (para mim) é com a indexação. Usando XML com planos de consulta, porque todo mundo os pegou, vamos fazer uma tabela:
SELECT TOP 1000
ID = IDENTITY(INT,1,1),
deq.query_plan
INTO dbo.index_test
FROM sys.dm_exec_cached_plans AS dec
CROSS APPLY sys.dm_exec_query_plan(dec.plan_handle) AS deq
ALTER TABLE dbo.index_test ADD CONSTRAINT pk_id PRIMARY KEY CLUSTERED (ID)
São apenas 1000 linhas, mas verificando o tamanho ...
sp_BlitzIndex @DatabaseName = 'StackOverflow', @SchemaName = 'dbo', @TableName = 'index_test'
Tem mais de 40 MB para apenas 1000 linhas. Supondo que você adicione 40 MB a cada 1000 linhas, isso pode ficar muito feio rapidamente. O que acontece quando você atinge 1 milhão de linhas? Isso significa apenas 1 TB de dados.
Todas as consultas que precisam usar o índice em cluster agora precisam ler todos esses dados BLOB no esclarecimento da 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 em armazenar BLOBs? Porque com certeza posso.
Expandindo-o para índices não clusterizados:
CREATE INDEX ix_noblob ON dbo.index_test (ID)
CREATE INDEX ix_returnoftheblob ON dbo.index_test (ID) INCLUDE (query_plan)
Você pode projetar seus índices não clusterizados para evitar amplamente a coluna BLOB, para que 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 principal, você terá índices gigantescos não clusterizados:
Mais problemas que eles causam:
- Se alguém executa uma
SELECT *
consulta, obtém todos os dados BLOB.
- Eles ocupam espaço em backups e restaurações, diminuindo a velocidade
- Eles diminuem a velocidade
DBCC CHECKDB
, porque eu sei que você está verificando corrupção, certo?
- E se você fizer alguma manutenção de índice, eles também diminuirão a velocidade.
Espero que isto ajude!
How large are these images, and how many do you expect to have? While I mostly agree with @sp_BlitzErik, I think there are some scenarios where it is ok to do this, and so it would help to have a clearer picture of what is actually being requested here.
Algumas opções a considerar que aliviam a maioria dos aspectos negativos apontados por Erik são:
Essas duas opções foram projetadas para serem um meio termo entre o armazenamento de BLOBs totalmente no SQL Server ou totalmente fora (exceto por um colun de seqüência de caracteres para manter o caminho). Eles permitem que os BLOBs façam parte do modelo de dados e participem das Transações sem desperdiçar espaço no buffer pool (ou seja, memória). Os dados do BLOB ainda estão incluídos nos backups, o que os faz ocupar mais espaço e levar mais tempo para fazer backup erestaurar. No entanto, tenho dificuldade em ver isso como um verdadeiro negativo, pois se ele faz parte do aplicativo, é necessário fazer backup de alguma forma, e ter apenas uma coluna de string contendo o caminho é completamente desconectado e permite que os arquivos BLOBs sejam recebidos. excluído sem indicação do que no DB (isto é, ponteiros inválidos / arquivos ausentes). Ele também permite que os arquivos sejam "excluídos" dentro do banco de dados, mas ainda existem no sistema de arquivos que precisará ser limpo (por exemplo, dor de cabeça). Mas, se os arquivos forem ENORMES, talvez seja melhor deixar completamente fora do SQL Server, exceto a coluna do caminho.
Isso ajuda com a pergunta "dentro ou fora", mas não toca na única tabela versus a questão da tabela múltipla. Posso dizer que, além dessa pergunta específica, certamente existem casos válidos para dividir tabelas em grupos de colunas com base nos padrões de uso. Frequentemente, quando se tem 50 ou mais colunas, há algumas que são acessadas com frequência e outras que não. Algumas colunas são gravadas com frequência, enquanto outras são lidas principalmente. Separar colunas de acesso frequente e acessado com pouca frequência em várias tabelas com um relacionamento de 1: 1 costuma ser benéfico, porque por que desperdiçar o espaço no Buffer Pool para dados que você provavelmente não está usando (semelhante ao por que armazenar imagens grandes regularmente
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. Obviamente, você também apresenta alguma ineficiência ao precisar duplicar a PK, e agora às vezes 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 melhor depende do seu ambiente e do que você está tentando realizar.
Não tão simples. Você pode encontrar algumas informações boas aqui: Qual é o tamanho do ponteiro LOB para tipos (MAX) 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):fonte
Se os dados precisarem 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 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 a 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 coloca mais de 8000 bytes no BLOB, é possível que ele seja armazenado em linha por algumas linhas. Você pode não querer isso, porque isso atrasará as consultas que acessam dados usando o índice clusterizado, mesmo que a coluna não seja necessária. 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 que contém uma coluna BLOB. Essa limitação foi removida será removida no SQL Server 2017.
Se você 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.
fonte