giovedì 25 luglio 2019

Dimensione tabelle in Sql Server

Ci sono diversi modi per conoscere l'effettiva dimensione in Kb/Mb di una tabella

Usando Sql Server Management Studio è possibile cliccare con il tasto destro sul database, scegliere dal menu la voce Report, quindi la voce "Report Standard" e infine la voce "Spazio su disco utilizzato per tabella".


Sempre con Sql Server Management Studio, selezionare prima la voce "Tabelle" nell'elenco di sinistra. Nella finestra "Dettagli esplora oggetti", una volta visualizzate tutte le tabelle è possibile indicare quali colonne vogliamo visualizzare. Fra le colonne che per default sono deselezionate ci sono : "Spazio utilizzato per i dati (KB)" e "Spazio utilizzato per gli indici (KB)"


L'ultimo modo per determinare lo spazio utilizzato dalle tabelle e degli indici di un database è quello di eseguire la seguente query (thanks Gianni GC Ceccanti 19/03/2021): 

select cast(Tabella as char(50)) as "Tabella", 
       max(Record) as "N. Record",  --max perché in base agli inidici cambia, il max corrisponde al totale sulla tabella
       sum(AllocatoTabellaMB) + sum(AllocatoIndiceMB) as "Totale Allocato (MB)", -- allocato su disco
       sum(AllocatoTabellaMB) as "Allocato Tabella (MB)", -- allocato su disco
       sum(AllocatoIndiceMB) as "Allocato Indice (MB)", -- allocato su disco
       sum(InutilizzatoMB) as "Inutilizzato (MB)" -- differenza tra spazio allocato e spazio utilizzato, quindi disponibile prima che SQLServera allochi nuovo spazio
  FROM (
      SELECT t.name AS "Tabella",
            p.rows as "Record",
            isnull( i.name , '_tabella_' ) as Tipo,
            (case when i.name is null then  CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) else 0 end) AS AllocatoTabellaMB,
            (case when i.name is not null then  CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) else 0 end) AS AllocatoIndiceMB,
            CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2) AS NUMERIC(36, 2)) AS InutilizzatoMB
       FROM sys.tables t
            INNER JOIN sys.indexes i ON t. object_id = i.object_id
            INNER JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
            INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
            LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
      WHERE t.name NOT LIKE 'dt%' 
         AND t.is_ms_shipped = 0
         AND i.OBJECT_ID > 255 
      GROUP BY  t.name, s.name, p.rows, i.name
      ) as innertable
GROUP BY Tabella
ORDER BY sum(AllocatoTabellaMB) + sum(AllocatoIndiceMB) DESC, Tabella
La query precedente, qui sotto, non teneva conto degli indici:
SELECT 
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows AS RowCounts,
    SUM(a.total_pages) * 8 AS TotalSpaceKB, 
    CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS TotalSpaceMB,
    SUM(a.used_pages) * 8 AS UsedSpaceKB, 
    CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS UsedSpaceMB, 
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB,
    CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSpaceMB
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN 
    sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN 
    sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, s.Name, p.Rows
ORDER BY 
    t.Name
Riferimenti : 
https://stackoverflow.com/questions/7892334/get-size-of-all-tables-in-database