Frammentazione dei file fisici del database SQL


19

So che ci sono davvero tre tipi di frammentazione di cui devo preoccuparmi come DBA:

  1. Frammentazione dell'indice nei file di dati SQL, inclusa la frammentazione dell'indice cluster (tabella). Identificarlo usando DBCC SHOWCONTIG (in SQL 2000) o sys.dm_ db_ index_ physical_ stats (nel 2005+).

  2. Frammentazione VLF all'interno dei file di registro SQL. Eseguire DBCC LOGINFO per vedere quanti VLF sono presenti in ciascuno dei file di registro SQL.

  3. Frammentazione dei file fisici dei file di database sul disco rigido. Diagnosticare ciò utilizzando l'utilità "Utilità di deframmentazione dischi" in Windows. (ispirato a questo eccellente post sul blog )

Molta attenzione è rivolta alla frammentazione dell'indice (vedi questa eccellente risposta Serverfault di Paul Randall), quindi non è questo il fulcro della mia domanda.

So di poter prevenire la frammentazione fisica (e la frammentazione VLF) quando il database è stato originariamente creato pianificando un file di dati e una dimensione logici previsti ragionevoli, poiché questa frammentazione si verifica più spesso a causa di crescite e riduzioni frequenti, ma ho alcune domande su come risolvere frammentazione fisica una volta identificata:

  • Prima di tutto, la frammentazione fisica è rilevante anche in una SAN Enterprise? Posso / dovrei usare l'utilità di deframmentazione di Windows su un'unità SAN o il team SAN dovrebbe utilizzare le utilità di deframmentazione interne? L'analisi di frammentazione che ottengo dallo strumento Windows è accurata anche quando eseguita su un'unità SAN?

  • Quanto è grande la frammentazione fisica delle prestazioni SQL? (Supponiamo un array di unità interne, in attesa dell'esito della domanda precedente.) È un affare PIÙ GRANDE della frammentazione dell'indice interno? O è davvero lo stesso tipo di problema (l'unità deve fare letture casuali invece di letture sequenziali)

  • La deframmentazione (o la ricostruzione) degli indici è una perdita di tempo se l'unità è fisicamente frammentata? Devo riparare l'uno prima di rivolgermi all'altro?

  • Qual è il modo migliore per correggere la frammentazione dei file fisici su una casella SQL di produzione? So che posso disattivare i servizi SQL ed eseguire Defrag di Windows, ma ho anche sentito parlare di una tecnica in cui si esegue un backup completo, si elimina il database, quindi si ripristina dal backup su un'unità vuota. Quest'ultima tecnica è consigliata? Il ripristino da un backup come questo crea anche indici da zero, eliminando la frammentazione degli indici interni? Oppure restituisce semplicemente l'ordine delle pagine allo stesso modo in cui è stato eseguito il backup? (Stiamo usando i backup di Quest Lightspeed con compressione, se questo è importante.)

AGGIORNAMENTO : Finora buone risposte sull'opportunità di deframmentare le unità SAN (NO) e se la deframmentazione dell'indice vale ancora su unità fisicamente frammentate (SÌ).

Qualcun altro si preoccupa di valutare i metodi migliori per eseguire effettivamente la deframmentazione? O una stima del tempo che ti aspetteresti sarebbe necessario per deframmentare un disco frammentato di grandi dimensioni, diciamo circa 500 GB? Rilevante, ovviamente, perché quello è il momento in cui il mio server SQL sarà inattivo!

Inoltre, se qualcuno ha qualche informazione aneddotica sui miglioramenti delle prestazioni di SQL che hai apportato correggendo la frammentazione fisica, sarebbe fantastico. Il post sul blog di Mike parla della scoperta del problema, ma non è specifico del tipo di miglioramento che ha apportato.

Risposte:


9

Penso che questo articolo offra un'eccellente panoramica della deframmentazione delle unità SAN

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

I punti di base sono che la deframmentazione non è consigliata nella memoria SAN perché è difficile correlare la posizione fisica dei blocchi sul disco quando la posizione è stata virtualizzata dalla SAN quando si presenta il LUN.

Se stavi utilizzando i mapping dei dispositivi RAW o hai accesso diretto a un set RAID che è il LUN con cui stai lavorando, potrei vedere la deframmentazione con un effetto positivo, ma se ti viene dato un LUN "virtuale" da un RAID condiviso- 5 set, n.


Articolo eccellente. Giusto per quanto riguarda le unità SAN.
BradC,

7

Più parti a questa domanda e risposta:

La frammentazione dei file fisici non è realmente rilevante per l'archiviazione SAN aziendale, come già sottolineato da Kevin, quindi nulla da aggiungere lì. Dipende davvero dal sottosistema I / O e dalla probabilità che si riesca a far passare le unità da I / O più casuali quando si esegue una scansione a I / O più sequenziali quando si esegue una scansione. per DAS, è più probabile che lo sia, per una complessa SAN slice-n-dice, probabilmente no.

Deframmentazione a livello di file system - fallo solo con SQL chiuso. Non ho mai avuto problemi qui (dal momento che non ho mai eseguito una deframmentazione in linea aperta di file di database SQL) ma ho sentito molte prove aneddotiche da parte di clienti e clienti di strani problemi di corruzione che si verificano. La saggezza generale non è di farlo con SQL online.

La frammentazione dell'indice è completamente ortogonale alla frammentazione dei file. SQL Server non ha idea della frammentazione dei file: troppi strati di virtualizzazione nel mezzo per avere qualche speranza di elaborare le geometrie dei sottosistemi I / O reali. Frammentazione dell'indice, tuttavia, SQL sa tutto. Senza ripetermi troppo dalla risposta a cui hai già fatto riferimento, la frammentazione dell'indice impedirà a SQL di eseguire un readahead con scansione a intervallo efficiente, indipendentemente dalla frammentazione (o meno) dei file a livello di file system. Quindi, assolutamente dovresti mitigare la frammentazione dell'indice se vedi prestazioni degradanti della query.

Non è necessario eseguirli in un ordine particolare, anche se se si prende cura della frammentazione del file system e quindi si ricostruiscono tutti gli indici e si causa una maggiore frammentazione del file system facendo crescere più file su un volume deframmentato, probabilmente si andrà a essere spuntato. Tuttavia causerà problemi di perf? Come discusso sopra, dipende :-D

Spero che sia di aiuto!


Ah, quindi la frammentazione dell'indice interno cambia effettivamente il comportamento dell'ottimizzatore, per favorire scansioni complete anziché ricerche di intervalli di indici adeguati?
BradC,

No. L'ottimizzatore non è a conoscenza del modo in cui i dati sono archiviati su disco, a parte il fatto che esistono indici, la loro dimensione e le statistiche di distribuzione del valore della colonna. È il motore di archiviazione che guida readahead e modifica le singole dimensioni I / O in base alla frammentazione logica di ciò che sta eseguendo la scansione.
Paul Randal,

3

Qual è il modo migliore per correggere la frammentazione dei file fisici su una casella SQL di produzione?

Corro la configurazione di SYSINTERNALS sui miei file di database.

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


Sembra interessante. Presumo dal momento che utilizza le API di deframmentazione di Windows, che i servizi SQL dovrebbero essere disattivati? O sarebbe eseguito mentre il server / database è online?
BradC,

L'ho usato con successo su database MSSQL Server online. Ma probabilmente quelli erano a basso traffico e piccoli database (meno di 10 GB)
Vincent Buck,

Questo è un grande strumento! Penso che le sue applicazioni per i database siano piuttosto limitate, come menzionato da altre persone, ma lo adoro per altri tipi di unità. La modalità di analisi -a è sicura mentre le cose sono in esecuzione. Tuttavia, non mi sentirei sicuro di eseguirlo su un'unità appartenente a un SQL Server live.
Kendra,

2

Consiglierei di ridimensionare il db in modo appropriato, spegnendo il server sql, copiando il file di database su un altro array di dischi e quindi copiandolo nuovamente per deframmentarlo. Molto più veloce dell'utilizzo di Windows Defrag nella mia esperienza.


1

Ho provato a deframmentare i dischi fisici in una soluzione scsi una volta, ma ho ottenuto un piccolo o nessun aumento delle prestazioni. La lezione che ho imparato è che se si sperimentano prestazioni lente a causa del sistema del disco, non ha nulla a che fare con la frammentazione, per quanto riguarda il file di dati, poiché utilizza l'accesso casuale.

Se i tuoi indici sono deframmentati e le statistiche vengono aggiornate (molto importante) e vedi ancora I / O come colli di bottiglia, allora soffri di cose diverse dalla frammentazione fisica. Hai usato più dell'80% del disco? Hai abbastanza unità? Le tue query sono abbastanza ottimizzate? Stai eseguendo molte scansioni di tabelle o, ancora peggio, molte ricerche di indici seguite da ricerche di indici in cluster? Guarda i piani di query e usa "imposta statistiche io on" per scoprire cosa sta realmente succedendo con la tua query. (cerca un numero elevato di letture logiche o fisiche)

Per favore fatemi sapere se sbaglio completamente.

/ Håkan Winther


No, non sbagli. Ma cercare di apportare alcuni miglioramenti a livello di server (se possibile) è un po 'più attraente che iniziare a immergersi nelle oltre 150.000 istruzioni SQL distinte che vengono eseguite durante i lavori di analisi settimanali (non un'esagerazione. Probabilmente un eufemismo, in realtà)
BradC

Se hai questo tipo di situazione, consiglierei Veritas I3 di analizzare il tuo ambiente per vedere quale collo di bottiglia soffri e cosa sta causando il collo di bottiglia. Veritas I3 tiene traccia di tutte le dichiarazioni e della frequenza con cui vengono chiamate ea quale costo. È un software eccellente.
Hakan Winther,

1

Forse gli indici non sono abbastanza ottimizzati per la tua applicazione e non hai Veritas I3 per ottimizzare il tuo database, quindi potresti usare un'istruzione come questa per trovare gli indici mancanti:

       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 ;

Oppure un'istruzione come questa per trovare indici non utilizzati nelle istruzioni selezionate e ridurre le prestazioni di aggiornamento / inserimento:

    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

Ho alcune altre dichiarazioni SQL che sto usando quando analizzo i problemi di prestazioni nell'ambiente di produzione, ma penso che questi due siano un buon inizio.

(Lo so, questo post è un po 'un argomento, ma ho pensato che potresti essere interessato poiché ha a che fare con la strategia di indicizzazione)

/ Håkan Winther


Script eccellenti, ne ho alcuni molto simili. Sfortunatamente, siamo ancora al 40% di SQL 2000 (incluso il server in questione), che non ha alcun equivalente a questi DMV a "indice mancante".
BradC,

Vedo, quindi ti consiglio di dare un'occhiata a Veritas I3. È un prodotto eccellente che è possibile utilizzare per ottimizzare i database, ma non è un software economico.
Hakan Winther,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.