En sus estimaciones de tamaño, ¿ha tenido en cuenta la cantidad de espacio ocupado por los índices? Además, si tiene campos de texto configurados como de varios bytes (en N[VAR]CHAR
lugar de [VAR]CHAR
) y los archivos de entrada son UTF-8 o un byte por carácter, eso aumentará sus requisitos de almacenamiento hasta en un factor de dos. Además, recuerde que si tiene una clave / índice agrupado en una tabla, el tamaño de esto afecta a todos los demás índices de la tabla porque incluyen el valor de la clave agrupada para cada fila (por ejemplo, si una tabla tiene un NCHAR (10) ) clave donde lo haría un INT y esa es su clave / índice agrupado; no solo está utilizando 16 bytes adicionales por fila en las páginas de datos, también desperdicia 16 bytes por fila en cualquier otro índice de esa tabla ) .
Además, se asignará algo de espacio pero no se utilizará, ya sea porque el motor de base de datos ha dejado algo de espacio asignado después de las eliminaciones para que pueda usarse nuevamente rápidamente para nuevos datos en esa tabla o porque el patrón de inserciones y eliminaciones ha dejado muchas páginas solo parte lleno.
Tu puedes correr:
SELECT o.name
, SUM(ps.reserved_page_count)/128.0 AS ReservedMB
, SUM(ps.used_page_count)/128.0 AS UsedMB
, SUM(ps.reserved_page_count-ps.used_page_count)/128.0 AS DiffMB
FROM sys.objects o
JOIN sys.dm_db_partition_stats ps ON o.object_id = ps.object_id
WHERE OBJECTPROPERTYEX(o.object_id, 'IsMSShipped') = 0
GROUP BY o.name
ORDER BY SUM(ps.reserved_page_count) DESC
para echar un vistazo rápido a las tablas que ocupan espacio.
También EXEC sp_spaceused
ejecutar dentro de ese DB devolverá dos conjuntos de resultados. El primero enumera el espacio total asignado en el sistema de archivos para los archivos de datos y cuánto de eso no está asignado, el segundo enumera cuánto del espacio asignado se usa para páginas de datos, páginas de índice o no se utiliza actualmente.
sp_spaceused
también devolverá el espacio utilizado por un objeto determinado, por lo que puede hacer un bucle para crear una tabla para el análisis:
-- TEMP TABLES FOR ANALYSIS
CREATE TABLE #tTables (sName NVARCHAR(MAX), iRows BIGINT, iReservedKB BIGINT, iDataKB BIGINT, iIndexKB BIGINT, iUnusedKB BIGINT)
CREATE TABLE #tTmp (sName NVARCHAR(MAX), iRows BIGINT, sReservedKB NVARCHAR(MAX), sDataKB NVARCHAR(MAX), sIndexKB NVARCHAR(MAX), sUnusedKB NVARCHAR(MAX))
-- COLLECT SPACE USE PER TABLE
EXEC sp_msforeachtable 'INSERT #tTmp EXEC sp_spaceused [?];'
-- CONVERT NUMBER-AS-TEXT COLUMNS TO NUMBER TYPES FOR EASIER ANALYSIS
INSERT #tTables SELECT sName, iRows
, CAST(REPLACE(sReservedKB, ' KB', '') AS BIGINT)
, CAST(REPLACE(sDataKB , ' KB', '') AS BIGINT)
, CAST(REPLACE(sIndexKB , ' KB', '') AS BIGINT)
, CAST(REPLACE(sUnusedKB , ' KB', '') AS BIGINT)
FROM #tTmp
DROP TABLE #tTmp
-- DO SOME ANALYSIS
SELECT sName='TOTALS', iRows=SUM(iRows), iReservedKB=SUM(iReservedKB), iDataKB=SUM(iDataKB), iIndexKB=SUM(iIndexKB), iUnusedKB=SUM(iUnusedKB) FROM #tTables ORDER BY sName
SELECT * FROM #tTables ORDER BY iReservedKB DESC
-- CLEAN UP
DROP TABLE #tTables
El código anterior generará todos los tamaños de tabla en una lista, más una sola fila para los totales. Si es necesario, puede utilizar las diversas vistas del sistema (como sys.objects
y sys.dm_db_partition_stats
utilizado en la primera consulta anterior, consulte http://technet.microsoft.com/en-us/library/ms177862.aspx para obtener más detalles) para obtener más detalles, como El espacio utilizado por cada índice.
Hay tres clases de espacio no utilizado en un archivo de datos:
- Aquello que no está asignado a nada (esto se muestra en el primer conjunto de resultados
sp_spaceused
sin ningún objeto especificado)
- Lo que se asigna a un objeto (reservado) pero no se usa actualmente (esto se muestra en el recuento "no utilizado" en
sp_spaceused
la salida de.
- Eso está bloqueado en páginas parcialmente utilizadas (se verá que se usará ya que todo se asigna en fragmentos de una sola página, una página tiene una longitud de 8,192 bytes). Esto es más difícil de detectar / calcular. Se debe a una combinación de dos factores:
- Dividir páginas. A medida que se agregan datos, a menudo terminas con páginas parcialmente vacías (el motor de almacenamiento siempre puede normalizar el contenido de la página, pero esto sería muy ineficiente), y como las filas se eliminan, los contenidos de la página no se empaquetan automáticamente (nuevamente podrían estar, pero el extra carga de E / S es generalmente lejos de la pena).
- El motor de almacenamiento no dividirá una fila en varias páginas (esto junto con el tamaño de página de donde proviene el límite de 8,192 bytes por fila). Si sus filas son de tamaño fijo y ocupan 1.100 bytes cada una, entonces va a "desperdiciar" al menos 492 bytes de cada bloque de datos asignado a esa tabla (7 filas ocupan 7.700 bytes y una octava no encajará, por lo que el resto de bytes ganará " t ser utilizado). Cuanto más anchas son las filas, peor puede ser. Las tablas / índices con filas de longitud variable (que son mucho más comunes que las de longitud completamente fija) generalmente son bastante mejores (pero son menos fáciles de calcular).
Otra advertencia aquí son los objetos grandes ( TEXT
columnas,[N]VARCHAR(MAX)
valores por encima de un cierto tamaño, etc.) ya que se colocan fuera de la página, solo toman 8 bytes en los datos de la fila principal para mantener un puntero a los datos en otro lugar) para que pueda romper el límite de 8,192 bytes por fila.
tl; dr: Estimar los tamaños de base de datos esperados puede ser mucho más complicado de lo que es natural suponer inicialmente.