Retrieve SiteCollection usage information and disk space

Quando si ha la necessità di misurare il size su disco ed il contenuto del ContentDB di un determinato SPSite i metodi che possiamo utilizzare sono parecchi, alcuni più efficienti degli altri e/o eventualmente bypassare l’utilizzo del OM messo a disposizione da MOSS.

In questo caso specifico abbiamo la necessità di monitorare il size del ContentDB di un determinato SPSite onde evitare il raggiungimento dei famigerati 100GB raccomandati dal capacity planning di riferimento.

Possiamo scegliere tra tre diversi metodi, oguno con una propria particolarità in base a diversi scenari di utilizzo.

Stored Procedure

Possiamo ad esempio misurare lo spazio fisico che il ContentDB occupa nel filesystem utilizzando la sp di sistema sp_spaceused. Questa misurazione è puntuale e può comprendere sia il LogDB che l’mdf vero e proprio e consiste nell’esecuzione della sp di sistema tramite il passaggio del nome DB che vogliamo monitorare. Non si fa uso dell’OM di MOSS, maggiormente performante ma occorre eseguire la sp nella stessa istanza SQL in cui è gestito il ContentDB di riferimento. Vi giro un esempio che prende in input il nome del database (@SourceDB) ed il sorting delle righe della tabella di output (@SortBy).

   1: CREATE PROCEDURE [dba_SpaceUsed]
   2:  
   3:     @SourceDB varchar ( 128 ) = null, 
   4:     @SortBy char(1) = 'S' 
   5:  
   6: AS
   7:  
   8: SET NOCOUNT ON
   9: DECLARE @sql nvarchar (4000)
  10: IF @SourceDB IS NULL BEGIN
  11:     SET @SourceDB = DB_NAME () 
  12: END
  13:  
  14: CREATE TABLE #Tables  (    [schema] sysname
  15:                         , TabName sysname 
  16:                         )
  17: SELECT @sql =  'INSERT #tables ([schema], [TabName]) 
  18:                 SELECT TABLE_SCHEMA, TABLE_NAME 
  19:                 FROM ['+ @SourceDB +'].INFORMATION_SCHEMA.TABLES
  20:                 WHERE TABLE_TYPE = ''BASE TABLE'''
  21: EXEC (@sql)
  22: CREATE TABLE #TabSpaceTxt (
  23:                          TabName sysname
  24:                       , [Rows] varchar (11)
  25:                       , Reserved varchar (18)
  26:                       , Data varchar (18)
  27:                       , Index_Size varchar ( 18 )
  28:                       , Unused varchar ( 18 )
  29:                             )
  30: CREATE TABLE #TabSpace ( [Schema] sysname
  31:                       , TabName sysname
  32:                       , [Rows] bigint
  33:                       , ReservedMB numeric(18,3)
  34:                       , DataMB numeric(18,3)
  35:                       , Index_SizeMB numeric(18,3)
  36:                       , UnusedMB numeric(18,3)
  37:                         )
  38: DECLARE @Tab sysname, @Sch sysname 
  39: DECLARE TableCursor CURSOR FOR
  40:     SELECT [SCHEMA], TabNAME 
  41:     FROM #tables
  42:     OPEN TableCursor;
  43:     FETCH TableCursor into @Sch, @Tab;
  44: WHILE @@FETCH_STATUS = 0 BEGIN
  45:     SELECT @sql = 'exec [' + @SourceDB 
  46:                 + ']..sp_executesql N''insert #TabSpaceTxt exec sp_spaceused '
  47:                 + '''''[' + @Sch + '].[' + @Tab + ']' + '''''''';
  48:     Delete from #TabSpaceTxt; 
  49:     EXEC (@sql);
  50:     INSERT INTO #TabSpace
  51:     SELECT @Sch
  52:          , [TabName]
  53:          , convert(bigint, rows)
  54:          , convert(numeric(18,3), convert(numeric(18,3), 
  55:                 left(reserved, len(reserved)-3)) / 1024.0) 
  56:                 ReservedMB
  57:          , convert(numeric(18,3), convert(numeric(18,3), 
  58:                 left(data, len(data)-3)) / 1024.0) DataMB
  59:          , convert(numeric(18,3), convert(numeric(18,3), 
  60:                 left(index_size, len(index_size)-3)) / 1024.0) 
  61:                  Index_SizeMB
  62:          , convert(numeric(18,3), convert(numeric(18,3), 
  63:                 left(unused, len([Unused])-3)) / 1024.0) 
  64:                 [UnusedMB]
  65:         FROM #TabSpaceTxt;
  66:     FETCH TableCursor into @Sch, @Tab;
  67: END;
  68: CLOSE TableCursor;
  69: DEALLOCATE TableCursor;
  70: IF @SortBy = 'N' 
  71:     SELECT * FROM #TabSpace
  72:        ORDER BY [Schema] asc, [TabName] asc
  73: ELSE IF @SortBy = 'T'  
  74:     SELECT * FROM #TabSpace
  75:        ORDER BY [TabName] asc, [Schema] asc
  76: ELSE  
  77:     SELECT * FROM #TabSpace
  78:        ORDER BY ReservedMB desc
  79: ;
  80: DROP TABLE #Tables
  81: DROP TABLE #TabSpaceTxt
  82: DROP TABLE #TabSpace

Il risultato dell’esecuzione di questa sp è la visualizzazione di dati di occupazione su disco in base all’elenco completo di tabelle che sono contenute nel DB. I valori sono espressi in MB e basta fare la somma delle righe per avere il size totale di occupazione su disco del ContentDB di riferimento.

SPSite (ContentDatabase)

Se invece abbiamo bisogno di un’astrazione più ad alto livello possiamo interfacciarci direttamente con l’OM di MOSS e recuperare la proprietà DiskSizeRequired dell’oggetto ContentDataBase afferente alla classe SPSite.

   1: private ulong CheckSiteDiskSpaceOccupied(string url)
   2:         {
   3:  
   4:             using (SPSite site = new SPSite(url))
   5:             {
   6:                 return site.ContentDatabase.DiskSizeRequired;    
   7:             }
   8:  
   9:         }

Il valore ritornato è un ULong (unsigned) e riporta il valore in bytes necessario ad effettuare un restore (full backup) del ContentDB di riferimento. Questo valore comprende anche la quantità di spazio necessaria alla ricostruzione dei log e di eventuali indici: può essere quindi maggiore del primo esempio.

 SPSite (UsageInfo)

In quest’ultimo esempio invece ritorniamo il valore totale in bytes che viene consumato da tutti gli oggetti (metadata, SPList, ecc …) di un determinato SPSite.

   1: private long CheckSiteContentUsage(string url) 
   2:         {
   3:  
   4:             using (SPSite site = new SPSite(url))
   5:             {
   6:  
   7:                 SPSite.UsageInfo info = site.Usage;
   8:                 return info.Storage;
   9:  
  10:             }
  11:         
  12:         }

In questo caso l’oggetto UsageInfo ritorna un indicatore non aggiornato in tempo reale, in quanto appunto non basa la sua persistenza su informazioni che vengono recuperate da filesystem ma sul lavoro di timerjob che controllano periodicamente l’utilizzo degli oggetti del SPSite di riferimento.

In base alle vostre necessità selezionate il modo migliore, se siete nella stessa instanza potete utilizzare il primo metodo, altrimenti se occorrono dati puntuali utilizzate l’OM e magari ponderate bene l’utilizzo della struttura UsageInfo per elaborare le informazioni di utilizzo sui singoli oggetti del SPSite di riferimento.

Leave a Reply