Fragmentación de archivos físicos de la base de datos SQL

19

Sé que realmente hay tres tipos de fragmentación que me deben preocupar como DBA:

  1. Fragmentación de índice en los archivos de datos SQL, incluida la fragmentación de índice agrupado (tabla). Identifique esto usando DBCC SHOWCONTIG (en SQL 2000) o sys.dm_ db_ index_ physical_ stats (en 2005+).

  2. Fragmentación de VLF dentro de los archivos de registro SQL. Ejecute DBCC LOGINFO para ver cuántos VLF hay en cada uno de sus archivos de registro SQL.

  3. Fragmentación de archivos físicos de los archivos de la base de datos en el disco duro. Diagnostique esto utilizando la utilidad "Desfragmentador de disco" en Windows. (inspirado en esta excelente publicación de blog )

Se presta mucha atención a la fragmentación del índice (consulte esta excelente respuesta de Serverfault de Paul Randall), por lo que ese no es el enfoque de mi pregunta.

Sé que puedo evitar la fragmentación física (y la fragmentación de VLF) cuando la base de datos se crea originalmente planificando un archivo de datos y un tamaño de registro razonables, porque esta fragmentación ocurre con mayor frecuencia debido a crecimientos y reducciones frecuentes, pero tengo algunas preguntas sobre cómo solucionar fragmentación física una vez que se identifica:

  • En primer lugar, ¿es la fragmentación física incluso relevante en una SAN empresarial? ¿Puedo / debo usar el Desfragmentador de Windows en una unidad SAN, o el equipo de SAN debe usar utilidades de desfragmentación internas? ¿El análisis de fragmentación que obtengo de la herramienta de Windows es incluso preciso cuando se ejecuta en una unidad SAN?

  • ¿Qué tan importante es la fragmentación física en el rendimiento de SQL? (Supongamos una matriz de unidades internas, en espera del resultado de la pregunta anterior). ¿Es un acuerdo MÁS GRANDE que la fragmentación del índice interno? ¿O es realmente el mismo tipo de problema (la unidad tiene que hacer lecturas aleatorias en lugar de lecturas secuenciales)

  • ¿Desfragmentar (o reconstruir) los índices es una pérdida de tiempo si la unidad está físicamente fragmentada? ¿Tengo que arreglar uno antes de dirigirme al otro?

  • ¿Cuál es la mejor manera de arreglar la fragmentación de archivos físicos en un cuadro SQL de producción? Sé que puedo desactivar los servicios SQL y ejecutar Windows Defrag, pero también escuché sobre una técnica en la que haces una copia de seguridad completa, sueltas la base de datos y luego la restauras desde una copia de seguridad a una unidad vacía. ¿Se recomienda esta última técnica? ¿Restaurar desde una copia de seguridad como esta también genera índices desde cero, eliminando la fragmentación interna del índice? ¿O simplemente devuelve el orden de las páginas al mismo que cuando se realizó la copia de seguridad? (Estamos utilizando copias de seguridad de Quest Lightspeed con compresión, si eso importa).

ACTUALIZACIÓN : buenas respuestas hasta ahora sobre si desfragmentar unidades SAN (NO) y si la desfragmentación de índice todavía vale la pena en unidades físicamente fragmentadas (SÍ).

¿A alguien más le interesa evaluar los mejores métodos para hacer la desfragmentación? ¿O una estimación del tiempo que esperaría que llevara desfragmentar una unidad de disco grande y fragmentada, digamos unos 500 GB? Relevante, obviamente, porque ese es el momento en que mi servidor SQL estará inactivo.

Además, si alguien tiene información anecdótica sobre las mejoras de rendimiento de SQL que ha realizado al corregir la fragmentación física, también sería genial. La publicación del blog de Mike habla sobre descubrir el problema, pero no es específico sobre qué tipo de mejora hizo.

BradC
fuente

Respuestas:

9

Creo que este artículo ofrece una excelente descripción general de la desfragmentación de unidades SAN

http://www.las-solanas.com/storage_virtualization/san_volume_defragmentation.php

Los puntos básicos son que no se recomienda la desfragmentación en el almacenamiento SAN porque es difícil correlacionar la ubicación física de los bloques en el disco cuando la SAN ha virtualizado la ubicación al presentar el LUN.

Si estaba utilizando asignaciones de dispositivos RAW o tiene acceso directo a un conjunto RAID que es el LUN con el que está trabajando, podría ver que la desfragmentación tiene un efecto positivo, pero si recibe un LUN "virtual" de un RAID compartido: 5 juegos, no.

Kevin Kuphal
fuente
Excelente articulo. Justo en el punto con respecto a las unidades SAN.
BradC
7

Múltiples partes de esta pregunta y respuesta:

La fragmentación de archivos físicos no es realmente relevante para el almacenamiento de Enterprise SAN, como ya señaló Kevin, por lo que no hay nada que agregar allí. Realmente se reduce al subsistema de E / S y la probabilidad de que pueda hacer que las unidades pasen de E / S más aleatorias al realizar una exploración a E / S más secuenciales al realizar una exploración. para DAS, es más probable que lo haga, para una SAN compleja de cortar y cortar, probablemente no.

Desfragmentación a nivel del sistema de archivos: solo hágalo con SQL apagado. Nunca he tenido problemas aquí (ya que nunca he realizado una desfragmentación en línea de archivos abiertos de bases de datos SQL), pero he escuchado mucha evidencia anecdótica de clientes y clientes sobre la ocurrencia de problemas de corrupción. La sabiduría general es no hacerlo con SQL en línea.

La fragmentación del índice es completamente ortogonal a la fragmentación de archivos. SQL Server no tiene idea de la fragmentación de archivos: hay demasiadas capas de virtualización en el medio para que tenga alguna esperanza de resolver las geometrías reales del subsistema de E / S. Sin embargo, la fragmentación del índice, SQL sabe todo. Sin repetirme demasiado de la respuesta a la que ya hizo referencia, la fragmentación del índice evitará que SQL realice una lectura eficiente del escaneo de rango, independientemente de cuán fragmentados (o no) estén los archivos en el nivel del sistema de archivos. Entonces, absolutamente debe mitigar la fragmentación del índice si observa un rendimiento de consulta degradante.

No tiene que hacer esto en ningún orden en particular, aunque si se ocupa de la fragmentación del sistema de archivos y luego reconstruye todos sus índices y causa más fragmentación del sistema de archivos al hacer crecer varios archivos en un volumen desfragmentado, probablemente ser marcado ¿Causará problemas de rendimiento? Como se discutió anteriormente, depende :-D

¡Espero que esto ayude!

Paul Randal
fuente
Ah, entonces, ¿la fragmentación interna del índice cambia realmente el comportamiento del optimizador, para favorecer los escaneos completos en lugar de las búsquedas de rango de índice adecuadas?
BradC
No. El optimizador no tiene conocimiento de cómo se almacenan los datos en el disco, aparte del hecho de que existen índices, su tamaño y las estadísticas de distribución de valores de columna. Es el motor de almacenamiento el que impulsa la lectura y altera los tamaños de E / S individuales en función de la fragmentación lógica de lo que está escaneando.
Paul Randal
3

¿Cuál es la mejor manera de arreglar la fragmentación de archivos físicos en un cuadro SQL de producción?

Ejecuto el contig de SYSINTERNALS en mis archivos de base de datos.

Ver http://technet.microsoft.com/en-us/sysinternals/bb897428.aspx

Vincent Buck
fuente
Parece interesante. Supongo que, dado que usa las API de desfragmentación de Windows, ¿los servicios SQL tendrían que estar desactivados? ¿O esto se ejecutaría mientras el servidor / base de datos está en línea?
BradC
Lo he usado con éxito en las bases de datos en línea del servidor MSSQL. Pero podría decirse que se trataba de bases de datos pequeñas y de poco tráfico (menos de 10 Gb)
Vincent Buck,
Esta es una gran herramienta! Creo que sus aplicaciones para bases de datos son bastante limitadas, como lo han mencionado otras personas, pero me encanta para otros tipos de unidades. El modo de análisis -a es seguro mientras se ejecutan las cosas. Sin embargo, no me sentiría seguro al ejecutarlo contra una unidad que pertenece a un SQL Server en vivo.
Kendra
2

Recomendaría dimensionar el db adecuadamente, cerrar el servidor sql, copiar el archivo de la base de datos a otra matriz de discos y luego copiarlo de nuevo para desfragmentarlo. Mucho más rápido que usar Windows Defrag en mi experiencia.


fuente
1

Traté de desfragmentar los discos físicos en una solución scsi una vez, pero obtuve poco o ningún aumento de rendimiento. La lección que aprendí es que si experimenta un rendimiento lento debido al sistema de disco, no tiene nada que ver con la fragmentación, en lo que respecta al archivo de datos, ya que está utilizando acceso aleatorio.

Si sus índices están desfragmentados y las estadísticas se actualizan (muy importante) y todavía ve E / S como un cuello de botella, entonces sufre otras cosas además de la fragmentación física. ¿Has usado más del 80% de la unidad? ¿Tienes suficientes unidades? ¿Sus consultas están lo suficientemente optimizadas? ¿Está haciendo mucho escaneo de tabla o, peor aún, mucha búsqueda de índice seguido de búsqueda de índice agrupado? Mire los planes de consulta y use "establecer estadísticas io on" para averiguar qué sucede realmente con su consulta. (busque una gran cantidad de lecturas lógicas o físicas)

Avísame si estoy completamente equivocado.

/ Håkan Winther

Hakan Winther
fuente
No, no te equivocas. Pero tratar de hacer algunas mejoras en todo el servidor (si es posible) es un poco más atractivo que comenzar a sumergirse en las más de 150,000 declaraciones SQL distintas que se ejecutan durante los trabajos de análisis semanales (no es una exageración. Probablemente un eufemismo, en realidad)
BradC
Si tiene ese tipo de situación, le recomendaría Veritas I3 para analizar su entorno para ver qué cuello de botella está sufriendo y cuál es la causa del cuello de botella. Veritas I3 realiza un seguimiento de todas las declaraciones y con qué frecuencia se llaman y a qué costo. Es un excelente software.
Hakan Winther
1

Tal vez los índices no estén lo suficientemente optimizados para su aplicación y no tenga Veritas I3 para optimizar su base de datos, entonces podría usar una declaración como esta para encontrar índices faltantes:

       SELECT
      mid.statement,
      mid.equality_columns,
      mid.inequality_columns,
      mid.included_columns,
      migs.user_seeks,
      migs.user_scans,
      migs.last_user_seek,
      migs.avg_user_impact,
      user_scans,
      avg_total_user_cost,
      avg_total_user_cost * avg_user_impact * (user_seeks + user_scans) AS [weight]--, migs.*--, mid.*
   FROM
      sys.dm_db_missing_index_group_stats AS migs
      INNER JOIN sys.dm_db_missing_index_groups AS mig
         ON (migs.group_handle = mig.index_group_handle)
      INNER JOIN sys.dm_db_missing_index_details AS mid
         ON (mig.index_handle = mid.index_handle)
   ORDER BY
      avg_total_user_cost * avg_user_impact * (user_seeks + user_scans) DESC ;

O una declaración como esta para encontrar índices que no se usan en las declaraciones de selección y disminuye el rendimiento de actualización / inserción:

    CREATE PROCEDURE [ADMIN].[spIndexCostBenefit]
    @dbname [nvarchar](75)
WITH EXECUTE AS CALLER
AS
--set @dbname='Chess'
declare @dbid nvarchar(5)
declare @sql nvarchar(2000)
select @dbid = convert(nvarchar(5),db_id(@dbname))

set @sql=N'select ''object'' = t.name,i.name
        ,''user reads'' = iu.user_seeks + iu.user_scans + iu.user_lookups
        ,''system reads'' = iu.system_seeks + iu.system_scans + iu.system_lookups
        ,''user writes'' = iu.user_updates
        ,''system writes'' = iu.system_updates
from '+ @dbname + '.sys.dm_db_index_usage_stats iu
,' + @dbname + '.sys.indexes i
,' + @dbname + '.sys.tables t
where 
    iu.database_id = ' + @dbid + '
and iu.index_id=i.index_id
and iu.object_id=i.object_id
and iu.object_id=t.object_id
AND (iu.user_seeks + iu.user_scans + iu.user_lookups)<iu.user_updates
order by ''user reads'' desc'

exec sp_executesql @sql

set @sql=N'SELECT
   ''object'' = t.name,
   o.index_id,
   ''usage_reads'' = user_seeks + user_scans + user_lookups,
   ''operational_reads'' = range_scan_count + singleton_lookup_count,
   range_scan_count,
   singleton_lookup_count,
   ''usage writes'' = user_updates,
   ''operational_leaf_writes'' = leaf_insert_count + leaf_update_count + leaf_delete_count,
   leaf_insert_count,
   leaf_update_count,
   leaf_delete_count,
   ''operational_leaf_page_splits'' = leaf_allocation_count,
   ''operational_nonleaf_writes'' = nonleaf_insert_count + nonleaf_update_count + nonleaf_delete_count,
   ''operational_nonleaf_page_splits'' = nonleaf_allocation_count
FROM
   ' + @dbname + '.sys.dm_db_index_operational_stats(' + @dbid + ', NULL, NULL, NULL) o,
   ' + @dbname + '.sys.dm_db_index_usage_stats u,
    ' + @dbname + '.sys.tables t
WHERE
   u.object_id = o.object_id
   AND u.index_id = o.index_id
    and u.object_id=t.object_id
ORDER BY
   operational_reads DESC,
   operational_leaf_writes,
   operational_nonleaf_writes'

exec sp_executesql @sql

GO

Tengo algunas otras declaraciones SQL que estoy usando cuando analizo problemas de rendimiento en el entorno de producción, pero creo que estas dos son un buen comienzo.

(Lo sé, esta publicación es un poco de tema, pero pensé que podría interesarte ya que tiene que ver con la estrategia de indexación)

/ Håkan Winther

Hakan Winther
fuente
Excelentes guiones, tengo algunos muy similares. Desafortunadamente, todavía estamos 40% de SQL 2000 (incluido el servidor en cuestión), que no tiene ningún equivalente a estos DMV de "índice perdido".
BradC
Ya veo, luego le recomiendo que eche un vistazo a Veritas I3. Es un excelente producto que puede usar para ajustar sus bases de datos, pero no es un software barato.
Hakan Winther