web-dev-qa-db-fra.com

Lignes directrices pour la maintenance des index de texte intégral

Quelles lignes directrices faut-il envisager pour gérer les index de texte intégral?

Dois-je RECONSTRUIRE ou RÉORGANISER le catalogue de texte intégral (voir BOL )? Qu'est-ce qu'une cadence d'entretien raisonnable? Quelles heuristiques (similaires aux seuils de fragmentation de 10% et 30%) pourraient être utilisées pour déterminer quand une maintenance est nécessaire?

(Tout ce qui suit est simplement des informations supplémentaires développant la question et montrant ce que j'ai pensé jusqu'à présent.)



Info supplémentaire: ma recherche initiale

Il existe de nombreuses ressources sur la maintenance de l'index b-tree (par exemple, cette question , scripts d'Ola Hallengren , et de nombreux articles de blog sur le sujet provenant d'autres sites). Cependant, j'ai constaté qu'aucune de ces ressources ne fournit de recommandations ou de scripts pour la maintenance des index de texte intégral.

Il y a documentation Microsoft qui mentionne que la défragmentation de l'index b-tree de la table de base, puis la réalisation d'une RÉORGANISATION sur le catalogue de texte intégral peuvent améliorer les performances, mais cela ne touche pas à des recommandations plus spécifiques .

J'ai également trouvé cette question , mais il est principalement axé sur le suivi des modifications (comment les mises à jour des données de la table sous-jacente sont propagées dans l'index de texte intégral) et non sur le type de maintenance régulièrement planifiée qui pourrait maximiser l'efficacité de l'indice.

Informations supplémentaires: tests de performances de base

Ce SQL Fiddle contient du code qui peut être utilisé pour créer un index de texte intégral avec AUTO suivi des modifications et examiner à la fois la taille et les performances de requête de l'index lorsque les données du tableau sont modifiées . Lorsque j'exécute la logique du script sur une copie de mes données de production (par opposition aux données fabriquées artificiellement dans le violon), voici un résumé des résultats que je vois après chaque étape de modification des données:

enter image description here

Même si les instructions de mise à jour de ce script étaient assez artificielles, ces données semblent montrer qu'il y a beaucoup à gagner d'une maintenance régulière.

Informations supplémentaires: idées initiales

Je pense à créer une tâche nocturne ou hebdomadaire. Il semble que cette tâche pourrait effectuer une RECONSTRUCTION ou une RÉORGANISATION.

Étant donné que les index de recherche en texte intégral peuvent être assez volumineux (des dizaines ou des centaines de millions de lignes), j'aimerais pouvoir détecter lorsque les index du catalogue sont suffisamment fragmentés pour qu'une RECONSTRUCTION/RÉORGANISATION soit justifiée. Je ne sais pas trop quelle heuristique pourrait avoir un sens pour cela.

30
Geoff Patterson

Je n'ai pas pu trouver de bonnes ressources en ligne, j'ai donc fait des recherches pratiques supplémentaires et j'ai pensé qu'il serait utile de publier le plan de maintenance en texte intégral que nous mettons en œuvre sur la base de ces recherches.


Notre heuristique pour déterminer quand une maintenance est nécessaire

enter image description here

Notre objectif principal est de conserver des performances de requête de texte intégral cohérentes à mesure que les données évoluent dans les tables sous-jacentes. Cependant, pour diverses raisons, il nous serait difficile de lancer une suite représentative de requêtes de texte intégral sur chacune de nos bases de données chaque nuit et d'utiliser les performances de ces requêtes pour déterminer le moment où la maintenance est nécessaire. Par conséquent, nous cherchions à créer des règles générales qui peuvent être calculées très rapidement et utilisées comme heuristique pour indiquer que la maintenance d'index de texte intégral peut être justifiée.

Au cours de cette exploration, nous avons constaté que le catalogue système fournit de nombreuses informations sur la façon dont un index de texte intégral donné est divisé en fragments. Cependant, il n'y a pas de "fragmentation%" officiel calculé (comme c'est le cas pour les index b-tree via sys.dm_db_index_physical_stats ). Sur la base des informations de fragment de texte intégral, nous avons décidé de calculer notre propre "fragmentation de texte intégral%". Nous avons ensuite utilisé un serveur de développement pour effectuer à plusieurs reprises des mises à jour aléatoires de 100 à 25 000 lignes à la fois sur une copie de 10 millions de lignes de données de production, enregistrer la fragmentation de texte intégral et effectuer une requête de texte intégral de référence à l'aide de CONTAINSTABLE.

Les résultats, comme le montrent les graphiques ci-dessus et ci-dessous, ont été très éclairants et ont montré que la mesure de fragmentation que nous avions créée est très fortement corrélée aux performances observées. Étant donné que cela est également lié à nos observations qualitatives en production, cela suffit pour que nous soyons à l'aise d'utiliser le% de fragmentation comme heuristique pour décider quand nos index de texte intégral doivent être maintenus.

enter image description here


Le plan de maintenance

Nous avons décidé d'utiliser le code suivant pour calculer un% de fragmentation pour chaque index de texte intégral. Tous les index de texte intégral de taille non triviale avec une fragmentation d'au moins 10% seront signalés pour être reconstruits par notre maintenance nocturne.

-- 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

Ces requêtes donnent des résultats tels que les suivants, et dans ce cas, les lignes 1, 6 et 9 seraient marquées comme étant trop fragmentées pour des performances optimales car l'index de texte intégral est supérieur à 1 Mo et au moins 10% fragmenté.

enter image description here


Cadence de maintenance

Nous avons déjà une fenêtre de maintenance nocturne et le calcul de la fragmentation est très bon marché à calculer. Nous allons donc exécuter cette vérification chaque nuit, puis effectuer uniquement l'opération la plus coûteuse de la reconstruction d'un index de texte intégral lorsque cela est nécessaire sur la base du seuil de fragmentation de 10%.


RECONSTRUIRE vs RÉORGANISER vs DROP/CREATE

SQL Server propose les options REBUILD et REORGANIZE, mais elles ne sont disponibles que pour un catalogue de texte intégral (qui peut contenir n'importe quel nombre d'index de texte intégral) dans son intégralité. Pour des raisons héritées, nous avons un seul catalogue de texte intégral qui contient tous nos index de texte intégral. Par conséquent, nous avons choisi de supprimer (DROP FULLTEXT INDEX) puis recréer (CREATE FULLTEXT INDEX) au niveau d'un index de texte intégral individuel.

Il serait peut-être plus idéal de diviser les index de texte intégral en catalogues séparés de manière logique et d'effectuer une REBUILD à la place, mais la solution drop/create fonctionnera pour nous en attendant.

37
Geoff Patterson