Tamaño de la base de datos: ¿MDF demasiado grande?

10

Mantengo una base de datos SQL Server 2005 que aloja aproximadamente 2.9Tb de datos (2 x 1.45Tb, tengo un esquema RAW y un esquema de ANÁLISIS, así que básicamente dos copias de los datos ingeridos). El modelo de recuperación es SIMPLE y .ldfestá a 6Gb.

Por alguna razón, el .mdfes 7.5Tb. Ahora, solo hay unas 2-3 columnas adicionales en las tablas de ANÁLISIS y no muchas NVARCHAR(MAX)columnas que, por lo que (puede haber entendido erróneamente, corríjame si me equivoco) pueden estar causando una asignación de espacio adicional. Eso fue después de reducir la base de datos en este momento: estaba a ~ 9Tb antes de eso. ¿Alguna idea?

Y, por favor, avíseme si tiene preguntas adicionales: soy muy nuevo en la administración de bases de datos y los esfuerzos de optimización (generalmente no hago este lado del trabajo :)).

¡Muchas gracias!

Andrija

Andrija_Bgd
fuente
Gracias Marc. ¿De alguna manera puedo mover esta pregunta allí o tengo que volver a publicar?
Saludos - como probablemente puedas adivinar, soy nuevo aquí :)

Respuestas:

11

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]CHARlugar 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_spaceusedejecutar 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.objectsy sys.dm_db_partition_statsutilizado 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:

  1. Aquello que no está asignado a nada (esto se muestra en el primer conjunto de resultados sp_spaceusedsin ningún objeto especificado)
  2. Lo que se asigna a un objeto (reservado) pero no se usa actualmente (esto se muestra en el recuento "no utilizado" en sp_spaceusedla salida de.
  3. 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 ( TEXTcolumnas,[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.

David Spillett
fuente
David: ¡muchas gracias por la respuesta detallada! Estoy analizando la base de datos en este momento y tanto sus respuestas como las de Kenneth han sido de gran ayuda para comprender los factores que influyen en el tamaño de la base de datos. ¡Siempre me preocupa la eficiencia (tanto en lo que respecta a la ingestión de datos como al uso de datos) y la información que ustedes proporcionaron ha sido invaluable!
Andrija_Bgd
6

Intenta ejecutar sp_spaceuseden tu base de datos. Como ejemplo, devuelve:

reserved           data               index_size         unused
------------------ ------------------ ------------------ ------------------
6032 KB            2624 KB            1664 KB            1744 KB

Para ejecutarlo en la base de datos, solo USEejecute la base de datos sp_spaceused.

Si aún muestra una gran cantidad de espacio no utilizado, puede intentar la reducción nuevamente. A veces me parece que toma varios intentos. También a veces encuentro que funciona mejor reducir el archivo individual en lugar de la base de datos en su conjunto. Sin embargo, lo que puede encontrar es que tiene 2.9Tb de datos y otros 4 + Tb de índices, en cuyo caso el 7.5TB es bastante razonable. Si desea tener una idea de la cantidad de espacio (datos e índice) de cada tabla, también puede ejecutar sp_spaceuseda nivel de tabla. Puede ejecutarlo en todas las tablas de la base de datos mediante el siguiente comando:

EXEC sp_msforeachtable 'EXEC sp_spaceused [?];'

Aunque la advertencia justa sp_msforeachtable no está documentada, no es compatible y se sabe que omite tablas. Por otro lado, yo también he tenido bastante suerte.

Dicho todo esto, su base de datos DEBE tener un cierto porcentaje de espacio libre en función de su crecimiento esperado. Básicamente, desea asegurarse de tener espacio para un crecimiento de entre 6 meses y un par de años. También querrá verificar su autogrowthconfiguración para asegurarse de que sea apropiada para su situación. Particularmente dado el tamaño de su base de datos, NO desea utilizar un% autogrowth.

Kenneth Fisher
fuente
¡Gracias! Usé sp_spaceused y parece que los datos reales realmente ocupan la cantidad de espacio indicada, por extraño que pueda parecerme dado el tamaño real de los archivos planos que se cargaron ... Los índices son pequeños (no tengo No creé ninguno adicional, ya que en mi caso habrían sido más un obstáculo que una ayuda), así que supongo que son solo las tablas reales las que son grandes ... ¡Un millón de gracias por su ayuda!
Andrija_Bgd
Las bases de datos ocupan más espacio que los archivos planos. Hay una cierta cantidad de gastos generales para las estructuras de filas y tablas y una cierta cantidad de desperdicio debido a la estructura de la página.
Kenneth Fisher
-1

Usando SQL Management Studio, 1. Haga clic derecho en la base de datos y luego 2. Haga clic en Tareas-> Reducir -> Archivos

Verá un cuadro de diálogo que muestra: a. Espacio asignado actualmente b. Espacio libre disponible + (% gratis)

Si su% Free es superior al 50%, puede considerar reducir el archivo. He visto este éxito hasta en un 90%. Si decido reducir el archivo, generalmente lo configuro en 2 o 3 gigas más que el espacio asignado actual. La mayoría de mis bases de datos son menos de 50 gigas. Entonces, si tiene un archivo mucho más grande, entonces puede hacerlo 10 gigas más grande. Por lo general, solo me preocupo por la reducción si voy a mover la base de datos a otro servidor, puede leer todo sobre la reducción de problemas en cualquier página sql.

Clark Vera
fuente