web-dev-qa-db-fra.com

Pourquoi ma base de données est-elle toujours fragmentée après avoir tout reconstruit et tout réindexé?

J'ai une base de données que j'ai essayé de défragmenter toutes les tables à la fois en exécutant ce T-SQL:

SELECT 
        'ALTER INDEX all ON ' + name + ' REORGANIZE;' + CHAR(10) +
        'ALTER INDEX all ON ' + name + ' REBUILD;'
    FROM sys.tables

Et puis copier et coller la sortie dans une nouvelle fenêtre de requête et l'exécuter. Je n'ai eu aucune erreur, mais j'ai encore une fragmentation. J'ai également essayé d'exécuter les deux commandes séparément et j'ai toujours une fragmentation. Note: J'ai été informé que REORGANIZE n'est pas nécessaire par Aaron, et je suis conscient que je pourrais utiliser SQL dynamique pour automatiser cela.

J'ai exécuté ceci pour déterminer que j'ai toujours une fragmentation:

SELECT * FROM 
sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, NULL) 
WHERE avg_fragmentation_in_percent > 0

Et j'ai eu:

database_id object_id   index_id    partition_number    index_type_desc alloc_unit_type_desc    index_depth index_level avg_fragmentation_in_percent    fragment_count  avg_fragment_size_in_pages  page_count  avg_page_space_used_in_percent  record_count    ghost_record_count  version_ghost_record_count  min_record_size_in_bytes    max_record_size_in_bytes    avg_record_size_in_bytes    forwarded_record_count  compressed_page_count
85  171147655   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   36.3636363636364    5   2.2 11  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  421576540   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   75  7   1.14285714285714    8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  965578478   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   14.7058823529412    6   5.66666666666667    34  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1061578820  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   40  4   1.25    5   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1109578991  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   30.7692307692308    5   2.6 13  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1205579333  2   1   NONCLUSTERED INDEX  IN_ROW_DATA 2   0   50  5   1.6 8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1493580359  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   50  6   1.66666666666667    10  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

Je sais que je manque quelque chose de vraiment basique, mais je ne sais pas quoi.

41
Justin Dearing

Les tables sont minuscules. Le nombre de pages dans vos tableaux est le suivant:

11, 8, 6, 5, 13, 8, 10

Ils occupent 480 Ko au total. Il n'y a littéralement rien à défragmenter.

Edit: Cela mérite un peu plus d'explications.

Une nouvelle table ou un nouvel index est généralement alloué sur les 8 premières pages d'une étendue mixte plutôt que uniforme. Ainsi, il est possible que chacune des 8 premières pages soit allouée à partir d'étendues mixtes différentes. Une table ou un index consommant 8 pages pourrait donc avoir 8 fragments, 1 sur chacune des 8 extensions mixtes différentes.

Les scripts de défragmentation les plus largement utilisés (quelques exemples liés ci-dessous) ont tendance à exclure les petites tables à cause de cela. IIRC, <500 pages est dans l'un ou les deux. À ces tailles, la défragmentation présente très peu d'avantages et les chiffres de fragmentation sont potentiellement faussés par les allocations d'étendues mixtes.

38
Mark Storey-Smith

Citation de " Meilleures pratiques de défragmentation d'index Microsoft SQL Server 20 ":

"La fragmentation affecte les E/S du disque. Par conséquent, concentrez-vous sur les index plus volumineux car leurs pages sont moins susceptibles d'être mises en cache par SQL Server. Utilisez le nombre de pages signalé par DBCC SHOWCONTIG pour avoir une idée de la taille des index (chaque page est 8 Ko.) En règle générale, vous ne devez pas vous préoccuper des niveaux de fragmentation des index de moins de 1 000 pages. Dans les tests, les index contenant plus de 10 000 pages ont réalisé des gains de performances, les plus importants gains sur les index avec beaucoup plus de pages (plus de 50 000 pages) . "

Donc, ce genre de réponses à votre question et soutient les réponses de Mark et Aaron.

Vous pouvez trouver de bonnes informations sur la fragmentation d'index dans les articles suivants de Brent Ozar:

Aussi ... un océan d'informations intéressantes sur les index en général (également sur les problèmes de fragmentation) peut être trouvé sur le blog de Kimberly Tripp .

20
Marian

Ce n'est pas censé répondre à votre question, mais cela ne rentrera jamais dans un commentaire. Vous pouvez créer ce script dynamiquement sans avoir à copier et coller la sortie dans une autre fenêtre. Tenant compte du fait qu'il n'y a absolument aucune raison de REORGANIZE puis REBUILD:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER INDEX all ON ' + name + ' REBUILD;
    ' FROM sys.tables;

PRINT @sql; -- to see the first 8,000 characters and make sure it checks out
-- EXEC sp_executesql @sql;
12
Aaron Bertrand