Fragmentación y reorganización de índices de bases de datos: Guía definitiva

Fragmentación de índices ralentiza considerablemente las consultas porque el orden físico de las páginas de índice difiere del orden lógico, lo que aumenta los tiempos de E/S, CPU y espera. En esta guía, le mostraré cómo Reorganización, la reconstrucción, el factor de llenado y el seguimiento trabajan juntos para reconocer de forma fiable y eliminar de forma sostenible la fragmentación.

Puntos centrales

  • Definición deLos árboles B* fragmentados generan más E/S y exploraciones más lentas.
  • CausasDivisiones de página, borrados, valores clave desplazados.
  • UmbralesReorganización a partir de ~5-30 %, reconstrucción a partir de ~30 %.
  • Enfoque MySQLOPTIMIZAR TABLA y factores de relleno.
  • AutomatizaciónTrabajos programados, operaciones en línea, métricas.

¿Qué significa técnicamente fragmentación de índices?

Me refiero como Fragmentación la discrepancia entre la secuencia lógica de claves y la cadena física de páginas de un índice de árbol B*. Muchos INSERT, UPDATE y DELETE dan lugar a huecos, divisiones y páginas de hoja desordenadas, que desencadenan más operaciones de lectura. El resultado: los escaneos saltan con más frecuencia, los accesos a la caché del búfer disminuyen y los costes de CPU aumentan. Incluso los planes ideales sufren porque la memoria entrega más lentamente las páginas dispersas. Por lo tanto, siempre presto atención al contexto de carga de trabajo, tamaño de los datos y disposición de la memoria.

Tipos de fragmentación y sus síntomas

Hago una distinción pragmática:

  • Fragmentación lógicaLas páginas de hojas ya no se concatenan en orden de clave. Los escaneos de rango requieren saltos adicionales, la lectura anticipada es menos efectiva.
  • Fragmentación internaLas páginas tienen mucho espacio no utilizado (bajos niveles de llenado). Hay que leer más páginas por línea de resultado; el tamaño del índice aumenta sin beneficio.
  • Fragmentación estructuralAltura de árbol desfavorable, nodos desequilibrados o montones con registros reenviados (por ejemplo, en SQL Server). Los accesos se vuelven más indirectos.

Esto puede medirse como un mayor número de páginas leídas por línea, latencias más altas durante los escaneos por rango u orden y una tasa de aciertos de caché decreciente. Siempre correlaciono las señales con las estadísticas de espera para evitar confusiones con problemas de red o almacenamiento.

Causas: Inserciones, actualizaciones, saltos de página

Las inserciones frecuentes llenan las páginas hasta el borde y, a continuación, una nueva tecla fuerza un Página dividida, lo que deja dos páginas a medio llenar. Las supresiones eliminan entradas, pero el espacio libre queda distribuido y no siempre se utiliza localmente con la siguiente inserción. Las actualizaciones que cambian las columnas clave desplazan registros y crean más huecos. Los patrones de clave aleatorios, como los GUID, aumentan aún más la dispersión y, por tanto, el desorden. Minimizo las divisiones utilizando la función Factor de llenado para que coincida con la carga de escritura.

Medir las pérdidas de rendimiento

No mido la fragmentación de forma aislada, sino en combinación con los tiempos de consulta, las lecturas de registro, las lecturas de página y las clases de espera. Si aumenta la latencia media de los escaneos de rangos y aumenta la CPU por consulta, compruebo primero los ratios físicos de los índices. Una fragmentación elevada aumenta el número de páginas leídas por igual número de líneas y comprime los tiempos de espera de E/S. Una comparación bien fundamentada antes y después de la reorganización o reconstrucción muestra el beneficio real. Para obtener información de fondo sobre el bloqueo, los planes y los cuellos de botella, merece la pena echar un vistazo a Rendimiento de la base de datos, clasificar correctamente los síntomas.

Métricas, esperas y eficiencia de la página en detalle

En la práctica, también observo:

  • Páginas por escaneado¿Cuántas páginas de hojas lee un escaneado de área típico? Si el valor aumenta con la misma cantidad de resultados, esto indica fragmentación o niveles de relleno demasiado bajos.
  • Golpe de lectura anticipadaLas cadenas fragmentadas sabotean los prefetches secuenciales; el efecto es menor en las SSD, pero no nulo, ya que la CPU, los latches y la caché siguen sufriendo.
  • Clases en esperaPAGEIOLATCH/IO-Waits (SQL Server), lectura secuencial/dispersa de archivos db (Oracle) o aumento de las latencias de lectura de InnoDB (MySQL) aumentan con saltos más fuertes en el índice.
  • Calidad de la cachéSi la tasa de éxito de la reserva de búferes disminuye paralelamente a la fragmentación, casi siempre merece la pena reconstruirla, especialmente en el caso de exploraciones de rangos grandes.

Analizar la fragmentación: SQL Server, MySQL, Oracle

Siempre empiezo el análisis con un Instantánea de la salud de los índices y filtrar los índices pequeños cuya utilización de páginas fluctúa estadísticamente. En SQL Server, sys.dm_db_index_physical_stats proporciona el grado de fragmentación junto con el recuento de páginas para que pueda ponderar los valores atípicos. Los valores por encima de 5-30 % indican reorganización, los valores atípicos por encima de 30 % indican una reconstrucción, especialmente con un recuento de páginas grande. En MySQL, compruebo las vistas SHOW TABLE STATUS o INFORMATION_SCHEMA y observo la longitud de los datos y los índices a lo largo del tiempo. En Oracle, también compruebo si hay disponible una reconstrucción en línea para Tiempo de inactividad que hay que evitar.

Consultas prácticas y ponderación

Trabajo con consultas sencillas y reutilizables y priorizo según el tamaño de la página y su relevancia:

  • Servidor SQLDetermino la fragmentación y filtro los índices pequeños.
    SELECT DB_NAME() AS db, OBJECT_NAME(i.object_id) AS obj, i.name AS idx,
           ips.index_type_desc, ips.page_count, ips.avg_fragmentation_in_percent
    FROM sys.indexes i
    CROSS APPLY sys.dm_db_index_physical_stats(DB_ID(), i.object_id, i.index_id, NULL, 'SAMPLED') ips
    WHERE ips.page_count >= 100
    ORDER BY ips.avg_fragmentation_in_percent DESC, ips.page_count DESC;
  • MySQL (InnoDB)Me fijo en el tamaño del índice, el espacio libre y la tasa de cambio.
    SELECT ESQUEMA_TABLA, NOMBRE_TABLA, MOTOR, LONGITUD_ÍNDICE, LIBRE_DATOS
    FROM información_esquema.TABLAS
    WHERE MOTOR = 'InnoDB'
      Y LONGITUD_ÍNDICE > 0
    ORDER BY (DATA_FREE) DESC;

    Al mismo tiempo, comparo los valores a lo largo del tiempo (por ejemplo, diariamente) para separar las tendencias reales de los valores atípicos. Para las estadísticas, utilizo ANALYZE TABLE con moderación si el optimizador asume cardinalidades incorrectas.

  • OracleCompruebo las estadísticas de los segmentos (espacios libres, extensiones) y la disponibilidad de REBUILD ONLINE para mantener previsibles las ventanas de mantenimiento.

Para mí es importante examinar únicamente los índices con una utilización elevada. Un índice fragmentado pero no utilizado tiene más probabilidades de ser candidato a la supresión que a la reorganización.

Reorganización frente a reconstrucción: Matriz de decisión

Elijo el método según el grado de Fragmentación y ventanas operativas, porque no todos los entornos pueden soportar picos intensivos de E/S. La reorganización reordena las páginas hoja, reduce los saltos lógicos, comprime hasta el factor de llenado y suele permanecer en línea. La reconstrucción reconstruye el índice, lo limpia completamente, devuelve memoria y actualiza las estadísticas, pero requiere CPU, E/S y, a menudo, bloqueos más largos. Los índices pequeños de menos de 100 páginas aproximadamente rara vez se benefician mucho, mientras que las estructuras grandes de 30 % de fragmentación o más ganan significativamente. Documento la decisión con cifras clave para que el efecto siga siendo comprensible y la Calendario de mantenimiento encaja.

Método Recursos necesarios Uso típico Efecto principal
Reorganización Bajo a medio ~5-30 % Fragmentación Reorganización, compresión para llenar el factor
Reconstruir Alta > 30 % Fragmentación Reconstrucción completa, liberación de memoria

Opciones en línea, bloqueos y efectos secundarios

Para un funcionamiento con pocas interrupciones, utilizo -cuando está disponible- Reconstrucciones en línea en. Presto atención a esto:

  • Edición/VersiónLas funciones en línea varían según la base de datos y la edición. Compruebo cada entorno por separado.
  • Bloqueos temporales de metadatosIncluso “en línea” suele requerir bloques al principio y al final. Los programo deliberadamente en fases tranquilas.
  • Rangos de temperatura/trabajoOpciones como SORT_IN_TEMPDB (SQL Server) reducen la carga del archivo de datos principal, pero requieren espacio de almacenamiento adicional.
  • ReplicaciónLas réplicas aumentan el volumen de registros. Superviso el retardo de las réplicas y acelero si es necesario para evitar retrasos.

Para los montones de SQL server tengo en cuenta Registros remitidos; En este caso, una reconstrucción de la tabla ayuda a eliminar los redireccionamientos. En Oracle, utilizo REBUILD ONLINE o MOVE PARTITION (con UPDATE INDEXES) para reducir el tiempo de inactividad.

Factor de llenado, división de páginas y memoria

Una adecuada Factor de llenado Yo establezco entre 70-90 % para las tablas que escriben mucho, de forma que las futuras inserciones puedan utilizar el espacio libre localmente. Si bajo demasiado el factor de llenado, el índice crece más rápido y ocupa más memoria; si lo pongo demasiado alto, aumentan las divisiones y la fragmentación. Por tanto, observo la relación entre la utilización de la página, la carga de escritura y el patrón de inserción a lo largo de varios ciclos. Para las reconstrucciones, defino deliberadamente el factor de llenado por índice, no de forma general para toda la base de datos. Un seguimiento regular evita que un compensación meses después.

Comprender los factores de llenado por plataforma

  • Servidor SQLFILLFACTOR es una propiedad del índice que tiene efecto durante la reconstrucción/creación. Yo establezco un valor más bajo para los índices secundarios muy volátiles y un valor más alto para las estructuras de lectura pesada. Documento el valor seleccionado para cada índice y lo recalibro tras los cambios en el perfil de carga.
  • MySQL (InnoDB)Con innodb_fill_factor Influyo en el espacio libre que InnoDB deja para las (re)construcciones. No se aplica al DML diario, pero con OPTIMIZE/ALTER ayuda a amortiguar las divisiones en el futuro. También planifico los hotspots (claves monótonas) de tal manera que se reduzca la competencia de latch y los splits.
  • Oracle y PostgreSQLparámetro STORAGE o. FILLFACTOR (Postgres) dejan espacio libre en las páginas. Para las tablas con mucha escritura, utilizo niveles de relleno conservadores y compenso la memoria extra con tiempos de escaneado sensiblemente mejores.

Específico para MySQL y WordPress

En MySQL me ayuda OPTIMIZAR TABLE en InnoDB para reorganizar tablas e índices asociados y devolver espacio libre. Las cargas de trabajo muy fragmentadas con muchos borrados también se benefician de la creación periódica de índices secundarios críticos. En las instalaciones de WordPress, reduzco el desorden, como las revisiones y los comentarios de spam, antes de optimizar para que haya que reordenar menos páginas. Combino estos pasos con una estrategia de índices limpios para wp_postmeta y tablas similares que suelen desencadenar escaneos. Encontrará una introducción práctica en la guía de Optimizar los índices de WordPress, que aborda los obstáculos típicos.

Práctica de MySQL: OPTIMIZE, particiones y efectos secundarios

También presto atención a InnoDB:

  • OPTIMIZAR TABLA reconstruye la tabla (y los índices) y puede ejecutarse en gran medida “in situ” dependiendo de la versión, pero siempre requiere meta bloqueos y espacio libre en el registro. Planifico ventanas de tiempo dedicadas a esto.
  • Particionamiento permite un mantenimiento específico: OPTIMIZAR LA PARTICIÓN sólo para las zonas calientes o muy borradas reduce los picos de E/S y el tiempo de ejecución.
  • ReplicaciónLas grandes reconstrucciones generan volumen de binlog y pueden retrasar las réplicas. Distribuyo el mantenimiento en varias noches o trabajo en particiones.
  • ANALIZAR TABLA renueva las estadísticas que el optimizador necesita para planificar mejor, sobre todo tras cambios estructurales masivos.

En entornos WordPress, reduzco por adelantado transitorios, las revisiones y los mensajes eliminados para que OPTIMIZE mueva menos datos. Para wp_postmeta, compruebo si las consultas se ejecutan específicamente a través de índices compuestos adecuados para evitar exploraciones amplias.

Características de PostgreSQL

Aunque aquí nos centremos en MySQL, tengo en cuenta los entornos heterogéneos:

  • VACIO/Autovacío evita el hinchamiento, pero no sustituye a REINDEX si las estructuras del árbol B están muy fragmentadas.
  • REINDEXAR SIMULTÁNEAMENTE permite crear nuevos índices en gran medida en línea con un bloqueo limitado.
  • factor de llenado por tabla/índice controla el aire libre para futuros INSERTs/UPDATEs. Las tablas con mucha escritura se benefician de valores más bajos.
  • Particiones por periodo alivian las ventanas de mantenimiento; REINDEX puede utilizarse específicamente para cada partición.

Mantenimiento automatizado y valores umbral

Automatizo la reorganización y la reconstrucción utilizando robust Umbrales y sólo activo índices con un page_count suficiente para evitar ruidos. Los trabajos se ejecutan en ventanas de mantenimiento, mientras que las operaciones largas las ejecuto mediante opciones en línea con el menor tiempo de inactividad posible. Un enfoque escalonado pospone las grandes reconstrucciones a los periodos de calma y ejecuta las pequeñas reorganizaciones con mayor frecuencia. Actualizo las estadísticas después de cambios importantes para que el optimizador seleccione mejores planes con prontitud. Las alertas se activan en cuanto la fragmentación o las latencias superan los límites predefinidos para que pueda actuar antes de que los usuarios se quejen.

Runbook: Secuencia de pasos para obtener resultados sostenibles

  1. IdentifiqueInstantánea de los N índices principales por tamaño y fragmentación, filtro de índices pequeños.
  2. Dar prioridad aOrdenar por criticidad de la carga de trabajo, page_count y carga de escaneo.
  3. PlanificaciónPrograme el reorg/rebuild en función de los valores umbral, calcule las opciones en línea y los requisitos de temp/log.
  4. RealiceEscalonamiento de objetos grandes, estrangulamiento de E/S, supervisión del retardo de replicación.
  5. EstadísticasActualice las estadísticas tras la reconstrucción/OPTIMIZACIÓN (o asegúrese de que se hace automáticamente).
  6. ValidarMedición antes/después: Latencia, páginas leídas, tiempos de espera, tasa de aciertos de caché.
  7. CalibreComprobar los factores de llenado y los umbrales, documentar las lecciones aprendidas.

Puesta a punto del alojamiento: normas prácticas

En entornos de alojamiento planifico análisis semanal, regulan la ventana de E/S de mantenimiento y se combinan con el almacenamiento en caché para mantener los hotsets en memoria. Los parámetros TempDB/redo/binlog y los medios de almacenamiento influyen significativamente en los efectos percibidos de la desfragmentación. También evalúo si los índices superfluos sólo generan costes, ya que cada índice adicional aumenta el trabajo de escritura y las posibilidades de fragmentación. Antes de cada nuevo índice, compruebo los patrones de carga de trabajo, las cardinalidades y la cobertura existente. Esbozo los escollos típicos en este resumen de Trampas de índice en MySQL, lo que evita errores de apreciación.

Costes/beneficios y cuando conscientemente no hago nada

No vale la pena mantener todas las fragmentaciones. Deliberadamente prescindo cuando:

  • El objeto es pequeño (por ejemplo, menos de 100 páginas) y fluctúa mucho: aquí es donde los beneficios se quedan cortos.
  • Las consultas son selectivas (principalmente búsquedas por clave) y no se ejecutan exploraciones de rango.
  • La carga de trabajo es transitoria (ventana de migración, archivando pronto) - entonces sólo planeo una reconstrucción final.

En su lugar, invierto en mejores índices, menos redundancia y una selección limpia de claves para que las futuras escisiones se produzcan con menos frecuencia.

¿Cuándo reorganizar, cuándo esperar?

Voy a lanzar un Reorganización si el grado de fragmentación aumenta moderadamente y se ven afectadas suficientes páginas como para tener un efecto real. Tras un borrado o archivado masivo, una redistribución ordenada suele aportar notables ganancias de escaneado. En caso de anomalías graves o de necesidades de almacenamiento, planifico una reconstrucción, preferiblemente en línea, para minimizar la interrupción de las operaciones. Suelo dejar intactos los índices pequeños, de menos de 100 páginas, porque su distribución fluctúa mucho y los beneficios son mínimos. Documento la decisión junto con las cifras de antes y después para que los ciclos futuros sean más fáciles de planificar.

Prevención a largo plazo mediante el diseño

Bien Diseño del sistema reduce la fragmentación incluso antes de la primera inserción, garantizando la coherencia de la selección de claves, los tipos de datos y la normalización. Evito las filas extra anchas, que permiten menos registros de datos por página y favorecen las divisiones. La partición separa los datos fríos de los calientes y reduce los efectos secundarios durante el mantenimiento y las copias de seguridad. Una cuidadosa optimización de las consultas reduce la dependencia de los costosos escaneos y ajusta los índices a los patrones del mundo real. A medida que cambian las cargas de trabajo, ajusto las definiciones de los índices de forma incremental en lugar de descartar estructuras enteras ad hoc.

Selección de teclas y patrón de inserción

La elección de la clave primaria influye decisivamente en el comportamiento de la división:

  • Teclas monótonas (por ejemplo, AUTO_INCREMENT, ID basados en el tiempo) agrupan las inserciones en el borde derecho, reducen la dispersión y las divisiones, pero pueden crear puntos calientes. Igualo los puntos calientes con buffering/batching.
  • Llaves aleatorias (por ejemplo, GUID/UUID v4) distribuyen la carga, pero aumentan la probabilidad de división. Las variantes secuenciales (por ejemplo, UUID basados en el tiempo) equilibran mejor la distribución y el orden.
  • Llave ancha aumentan el índice y el número de páginas necesarias. Las claves esbeltas y selectivas son más sostenibles.

Además, la compresión de líneas y páginas reduce la tasa de división porque hay espacio para más entradas por página. Sin embargo, siempre compruebo los costes de CPU y la disponibilidad de licencias/funciones antes de activar la compresión.

Brevemente resumido: Pasos con efecto

Empiezo con una Análisis de los índices más grandes y fragmentados, priorizar según el page_count y la criticidad de la carga de trabajo. A continuación, aplico medidas escalonadas: reorganizo los casos moderados, reconstruyo los casos pesados, reajusto los factores de llenado de cada índice. Los trabajos automatizados mantienen el orden sin intervención manual constante, mientras que las alertas se activan de forma fiable en caso de valores atípicos. Los entornos MySQL y WordPress se benefician notablemente si reduzco de antemano el desperdicio de datos y conservo únicamente los índices útiles. Con una supervisión coherente, umbrales claros y playbooks repetibles Actuación estable, incluso cuando los datos crecen rápidamente.

Artículos de actualidad