Pautas para el mantenimiento del índice de texto completo

29

¿Qué pautas deben considerarse para mantener los índices de texto completo?

¿Debería RECONSTRUIR o REORGANIZAR el catálogo de texto completo (ver BOL )? ¿Qué es una cadencia de mantenimiento razonable? ¿Qué heurística (similar a los umbrales de fragmentación del 10% y 30%) podría usarse para determinar cuándo se necesita mantenimiento?

(Todo lo que sigue es simplemente información adicional elaborada sobre la pregunta y que muestra lo que he pensado hasta ahora).



Información adicional: mi investigación inicial

Hay muchos recursos sobre el mantenimiento del índice b-tree (por ejemplo, esta pregunta , los scripts de Ola Hallengren y numerosas publicaciones de blog sobre el tema desde otros sitios). Sin embargo, descubrí que ninguno de estos recursos proporciona recomendaciones o scripts para mantener índices de texto completo.

Existe documentación de Microsoft que menciona que desfragmentar el índice b-tree de la tabla base y luego realizar una REORGANIZACIÓN en el catálogo de texto completo puede mejorar el rendimiento, pero no incluye recomendaciones más específicas.

También encontré esta pregunta , pero se centra principalmente en el seguimiento de cambios (cómo las actualizaciones de datos de la tabla subyacente se propagan en el índice de texto completo) y no en el tipo de mantenimiento programado regularmente que podría maximizar la eficiencia del índice.

Información adicional: pruebas de rendimiento básicas

Este SQL Fiddle contiene código que se puede usar para crear un índice de texto completo con AUTOseguimiento de cambios y examinar tanto el tamaño como el rendimiento de la consulta del índice a medida que se modifican los datos de la tabla. Cuando ejecuto la lógica del script en una copia de mis datos de producción (a diferencia de los datos fabricados artificialmente en el violín), aquí hay un resumen de los resultados que veo después de cada paso de modificación de datos:

ingrese la descripción de la imagen aquí

Aunque las declaraciones de actualización en este script fueron bastante artificiales, estos datos parecen mostrar que hay mucho que ganar con el mantenimiento regular.

Información adicional: ideas iniciales

Estoy pensando en crear una tarea nocturna o semanal. Parece que esta tarea podría realizar una RECONSTRUCCIÓN o REORGANIZAR.

Debido a que los índices de texto completo pueden ser bastante grandes (decenas o cientos de millones de filas), me gustaría poder detectar cuándo los índices dentro del catálogo están lo suficientemente fragmentados como para justificar una RECONSTRUCCIÓN / REORGANIZACIÓN. No estoy un poco claro sobre qué heurística podría tener sentido para eso.

Geoff Patterson
fuente

Respuestas:

36

No pude encontrar buenos recursos en línea, por lo que investigué un poco más y pensé que sería útil publicar el plan de mantenimiento de texto completo resultante que estamos implementando en base a esa investigación.


Nuestra heurística para determinar cuándo se necesita mantenimiento

ingrese la descripción de la imagen aquí

Nuestro objetivo principal es retener el rendimiento constante de las consultas de texto completo a medida que los datos evolucionan en las tablas subyacentes. Sin embargo, por diversas razones, sería difícil para nosotros lanzar un conjunto representativo de consultas de texto completo en cada una de nuestras bases de datos cada noche y utilizar el rendimiento de esas consultas para determinar cuándo se necesita mantenimiento. Por lo tanto, estábamos buscando crear reglas generales que puedan calcularse muy rápidamente y usarse como una heurística para indicar que el mantenimiento del índice de texto completo puede estar justificado.

En el curso de esta exploración, descubrimos que el catálogo del sistema proporciona mucha información sobre cómo un índice de texto completo se divide en fragmentos. Sin embargo, no hay un "% de fragmentación" oficial calculado (como lo hay para los índices b-tree a través de sys.dm_db_index_physical_stats ). En base a la información de fragmentos de texto completo, decidimos calcular nuestro propio "% de fragmentación de texto completo". Luego, utilizamos un servidor de desarrollo para realizar actualizaciones aleatorias de entre 100 y 25,000 filas a la vez en una copia de 10 millones de filas de datos de producción, registrar la fragmentación de texto completo y realizar una consulta de referencia de texto completo utilizando CONTAINSTABLE.

Los resultados, como se ve en los cuadros de arriba y abajo, fueron muy esclarecedores y mostraron que la medida de fragmentación que habíamos creado está muy relacionada con el rendimiento observado. Dado que esto también se relaciona con nuestras observaciones cualitativas en la producción, es suficiente para que nos sentimos cómodos usando el% de fragmentación como nuestra heurística para decidir cuándo nuestros índices de texto completo necesitan mantenimiento.

ingrese la descripción de la imagen aquí


El plan de mantenimiento

Hemos decidido usar el siguiente código para calcular un% de fragmentación para cada índice de texto completo. Cualquier índice de texto completo de tamaño no trivial con una fragmentación de al menos el 10% se marcará para ser reconstruido por nuestro mantenimiento nocturno.

-- Compute fragmentation information for all full-text indexes on the database
SELECT c.fulltext_catalog_id, c.name AS fulltext_catalog_name, i.change_tracking_state,
    i.object_id, OBJECT_SCHEMA_NAME(i.object_id) + '.' + OBJECT_NAME(i.object_id) AS object_name,
    f.num_fragments, f.fulltext_mb, f.largest_fragment_mb,
    100.0 * (f.fulltext_mb - f.largest_fragment_mb) / NULLIF(f.fulltext_mb, 0) AS fulltext_fragmentation_in_percent
INTO #fulltextFragmentationDetails
FROM sys.fulltext_catalogs c
JOIN sys.fulltext_indexes i
    ON i.fulltext_catalog_id = c.fulltext_catalog_id
JOIN (
    -- Compute fragment data for each table with a full-text index
    SELECT table_id,
        COUNT(*) AS num_fragments,
        CONVERT(DECIMAL(9,2), SUM(data_size/(1024.*1024.))) AS fulltext_mb,
        CONVERT(DECIMAL(9,2), MAX(data_size/(1024.*1024.))) AS largest_fragment_mb
    FROM sys.fulltext_index_fragments
    GROUP BY table_id
) f
    ON f.table_id = i.object_id

-- Apply a basic heuristic to determine any full-text indexes that are "too fragmented"
-- We have chosen the 10% threshold based on performance benchmarking on our own data
-- Our over-night maintenance will then drop and re-create any such indexes
SELECT *
FROM #fulltextFragmentationDetails
WHERE fulltext_fragmentation_in_percent >= 10
    AND fulltext_mb >= 1 -- No need to bother with indexes of trivial size

Estas consultas arrojan resultados como los siguientes, y en este caso las filas 1, 6 y 9 se marcarían como demasiado fragmentadas para un rendimiento óptimo porque el índice de texto completo es superior a 1 MB y al menos 10% fragmentado.

ingrese la descripción de la imagen aquí


Cadencia de mantenimiento

Ya tenemos una ventana de mantenimiento nocturno, y el cálculo de fragmentación es muy barato de calcular. Por lo tanto, realizaremos esta verificación cada noche y luego solo realizaremos la operación más costosa de reconstruir realmente un índice de texto completo cuando sea necesario en función del umbral de fragmentación del 10%.


RECONSTRUIR vs REORGANIZAR vs CAER / CREAR

Las ofertas REBUILDy REORGANIZEopciones de SQL Server , pero están disponibles solo para un catálogo de texto completo (que puede contener cualquier número de índices de texto completo) en su totalidad. Por razones heredadas, tenemos un único catálogo de texto completo que contiene todos nuestros índices de texto completo. Por lo tanto, hemos optado por soltar ( DROP FULLTEXT INDEX) y luego volver a crear ( CREATE FULLTEXT INDEX) en un nivel de índice de texto completo individual.

Podría ser más ideal dividir los índices de texto completo en catálogos separados de una manera lógica y realizar un REBUILDcambio, pero la solución drop / create funcionará para nosotros mientras tanto.

Geoff Patterson
fuente