Como de varchar
todos modos asigna espacio dinámicamente, mi pregunta es si el uso varchar(255)
es más eficiente o ahorra más espacio en comparación con el uso varchar(5000)
. ¿Si es así por qué?
Como de varchar
todos modos asigna espacio dinámicamente, mi pregunta es si el uso varchar(255)
es más eficiente o ahorra más espacio en comparación con el uso varchar(5000)
. ¿Si es así por qué?
Respuestas:
Sí, varchar(5000)
puede ser peor que varchar(255)
si todos los valores encajaran en este último. La razón es que SQL Server estimará el tamaño de los datos y, a su vez, las concesiones de memoria en función del tamaño declarado (no real ) de las columnas en una tabla. Cuando lo haya hecho varchar(5000)
, supondrá que cada valor tiene una longitud de 2.500 caracteres y reservará memoria en función de eso.
Aquí hay una demostración de mi reciente presentación de GroupBy sobre malos hábitos que hace que sea fácil probarlo por sí mismo (requiere SQL Server 2016 para algunas de las sys.dm_exec_query_stats
columnas de salida, pero aún debe ser demostrable con SET STATISTICS TIME ON
u otras herramientas en versiones anteriores); muestra una memoria más grande y tiempos de ejecución más largos para la misma consulta con los mismos datos ; la única diferencia es el tamaño declarado de las columnas:
-- 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];
Entonces, sí, dimensione correctamente sus columnas , por favor.
Además, volví a ejecutar las pruebas con varchar (32), varchar (255), varchar (5000), varchar (8000) y varchar (max). Resultados similares ( haga clic para ampliar ), aunque las diferencias entre 32 y 255, y entre 5,000 y 8,000, fueron insignificantes:
Aquí hay otra prueba con el TOP (5000)
cambio para la prueba más completamente reproducible por la que me acosaron sin cesar ( haga clic para agrandar ):
Entonces, incluso con 5,000 filas en lugar de 10,000 filas (y hay más de 5,000 filas en sys.all_columns al menos tan atrás como SQL Server 2008 R2), se observa una progresión relativamente lineal, incluso con los mismos datos, cuanto mayor sea el tamaño definido de la columna, se necesita más memoria y tiempo para satisfacer exactamente la misma consulta (incluso si no tiene sentido DISTINCT
).
varchar(450)
y varchar(255)
sería la misma? (¿O algo por debajo de 4000?)
rowcount*(column_size/2)
.