De varchar
qualquer maneira, aloque espaço dinamicamente, minha pergunta é se o uso deve varchar(255)
ser mais eficiente ou economizar mais espaço em comparação ao uso varchar(5000)
. Se sim, por que?
De varchar
qualquer maneira, aloque espaço dinamicamente, minha pergunta é se o uso deve varchar(255)
ser mais eficiente ou economizar mais espaço em comparação ao uso varchar(5000)
. Se sim, por que?
Respostas:
Sim, varchar(5000)
pode ser pior do que varchar(255)
se todos os valores se ajustarem ao último. O motivo é que o SQL Server estimará o tamanho dos dados e, por sua vez, as concessões de memória com base no tamanho declarado (não real ) das colunas em uma tabela. Quando você tiver varchar(5000)
, ele assumirá que todo valor possui 2.500 caracteres e reserva memória com base nisso.
Aqui está uma demonstração da minha recente apresentação do GroupBy sobre maus hábitos que facilita a prova por si mesmo (requer o SQL Server 2016 para algumas das sys.dm_exec_query_stats
colunas de saída, mas ainda deve ser comprovável com SET STATISTICS TIME ON
ou outras ferramentas em versões anteriores); ele mostra maior memória e mais longos tempos de execução para a mesma consulta contra os mesmos dados - a única diferença é o tamanho declarado das colunas:
-- create three tables with different column sizes
CREATE TABLE dbo.t1(a nvarchar(32), b nvarchar(32), c nvarchar(32), d nvarchar(32));
CREATE TABLE dbo.t2(a nvarchar(4000), b nvarchar(4000), c nvarchar(4000), d nvarchar(4000));
CREATE TABLE dbo.t3(a nvarchar(max), b nvarchar(max), c nvarchar(max), d nvarchar(max));
GO -- that's important
-- Method of sample data pop : irrelevant and unimportant.
INSERT dbo.t1(a,b,c,d)
SELECT TOP (5000) LEFT(name,1), RIGHT(name,1), ABS(column_id/10), ABS(column_id%10)
FROM sys.all_columns ORDER BY object_id;
GO 100
INSERT dbo.t2(a,b,c,d) SELECT a,b,c,d FROM dbo.t1;
INSERT dbo.t3(a,b,c,d) SELECT a,b,c,d FROM dbo.t1;
GO
-- no "primed the cache in advance" tricks
DBCC FREEPROCCACHE WITH NO_INFOMSGS;
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;
GO
-- Redundancy in query doesn't matter! Just has to create need for sorts etc.
GO
SELECT DISTINCT a,b,c,d, DENSE_RANK() OVER (PARTITION BY b,c ORDER BY d DESC)
FROM dbo.t1 GROUP BY a,b,c,d ORDER BY c,a DESC;
GO
SELECT DISTINCT a,b,c,d, DENSE_RANK() OVER (PARTITION BY b,c ORDER BY d DESC)
FROM dbo.t2 GROUP BY a,b,c,d ORDER BY c,a DESC;
GO
SELECT DISTINCT a,b,c,d, DENSE_RANK() OVER (PARTITION BY b,c ORDER BY d DESC)
FROM dbo.t3 GROUP BY a,b,c,d ORDER BY c,a DESC;
GO
SELECT [table] = N'...' + SUBSTRING(t.[text], CHARINDEX(N'FROM ', t.[text]), 12) + N'...',
s.last_dop, s.last_elapsed_time, s.last_grant_kb, s.max_ideal_grant_kb
FROM sys.dm_exec_query_stats AS s CROSS APPLY sys.dm_exec_sql_text(s.sql_handle) AS t
WHERE t.[text] LIKE N'%dbo.'+N't[1-3]%' ORDER BY t.[text];
Então, sim, dimensione corretamente suas colunas , por favor.
Além disso, refiz os testes com varchar (32), varchar (255), varchar (5000), varchar (8000) e varchar (max). Resultados semelhantes ( clique para ampliar ), embora as diferenças entre 32 e 255 e entre 5.000 e 8.000 fossem insignificantes:
Aqui está outro teste com a TOP (5000)
alteração do teste mais totalmente reprodutível sobre o qual eu estava sendo incessantemente atormentado ( clique para ampliar ):
Portanto, mesmo com 5.000 linhas em vez de 10.000 linhas (e há mais de 5.000 linhas em sys.all_columns pelo menos no SQL Server 2008 R2), uma progressão relativamente linear é observada - mesmo com os mesmos dados, quanto maior o tamanho definido da coluna, mais memória e tempo são necessários para satisfazer exatamente a mesma consulta (mesmo que ela não tenha sentido DISTINCT
).
varchar(450)
e varchar(255)
seria a mesma? (Ou qualquer coisa abaixo de 4000?)
rowcount*(column_size/2)
.