Dimensioni della tabella e dell'indice in SQL Server


91

Possiamo avere una query SQL che sostanzialmente aiuterà nella visualizzazione delle dimensioni di tabelle e indici in SQl Server.

In che modo SQL Server gestisce l'utilizzo della memoria per tabelle / indici?


1
Potresti anche trovare sp_helpdbutile la stored procedure
Zack Burt,

1
Ci sono già delle risposte, ma io personalmente uso la query in questo link: qualityofdata.com/2011/02/02/…
naiem

Risposte:


74

Il exec sp_spaceusedparametro senza mostra il riepilogo per l'intero database. La soluzione foreachtable genera un set di risultati per tabella, che SSMS potrebbe non essere in grado di gestire se si dispone di troppe tabelle.

Ho creato uno script che raccoglie le informazioni della tabella tramite sp_spaceusede visualizza un riepilogo in un unico set di record, ordinato per dimensione.

create table #t
(
  name nvarchar(128),
  rows varchar(50),
  reserved varchar(50),
  data varchar(50),
  index_size varchar(50),
  unused varchar(50)
)

declare @id nvarchar(128)
declare c cursor for
select '[' + sc.name + '].[' + s.name + ']' FROM sysobjects s INNER JOIN sys.schemas sc ON s.uid = sc.schema_id where s.xtype='U'

open c
fetch c into @id

while @@fetch_status = 0 begin

  insert into #t
  exec sp_spaceused @id

  fetch c into @id
end

close c
deallocate c

select * from #t
order by convert(int, substring(data, 1, len(data)-3)) desc

drop table #t

4
Lo script gestisce solo le tabelle nello schema "dbo". Se ho una tabella nel mio database con uno schema di "Audit", sp_spaceused deve essere chiamato in questo modo: exec sp_spaceused "Audit.Data". Quindi lo script deve essere modificato per fornire il nome della tabella preceduto dal nome dello schema (separato da un punto) in modo che restituisca dati sulle tabelle da altri schemi.
Baodad

1
Buon punto @Boadad ... dovrebbe essere una soluzione semplicissima. Sostituire "select name from sysobjects where xtype = 'U'" con questo dovrebbe fare il trucco: "selezionare '[' + sc.name + ']. [' + S.name + ']' FROM sysobjects s ​​INNER JOIN sys .schemas sc ON s.uid = sc.schema_id dove s.xtype = 'U' "Ottimo script, grazie!
DCaugs

invece di usare una tabella temporanea possiamo inserire dati in un'altra tabella che non è temporanea?
prab2112

@ PrabhakarPandey Certo, basta rimuovere il file #.
Racer SQL

120

sp_spaceused ti dà la dimensione di tutti gli indici combinati.

Se desideri la dimensione di ogni indice per una tabella, utilizza una di queste due query:

SELECT
    i.name                  AS IndexName,
    SUM(s.used_page_count) * 8   AS IndexSizeKB
FROM sys.dm_db_partition_stats  AS s 
JOIN sys.indexes                AS i
ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id
WHERE s.[object_id] = object_id('dbo.TableName')
GROUP BY i.name
ORDER BY i.name

SELECT
    i.name              AS IndexName,
    SUM(page_count * 8) AS IndexSizeKB
FROM sys.dm_db_index_physical_stats(
    db_id(), object_id('dbo.TableName'), NULL, NULL, 'DETAILED') AS s
JOIN sys.indexes AS i
ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id
GROUP BY i.name
ORDER BY i.name

I risultati sono generalmente leggermente diversi ma entro l'1%.


La prima query include le chiavi primarie, il che crea un po 'di confusione per un paio di motivi.
Quillbreaker

La seconda query Msg 102, Level 15, State 1, Line 5 - Incorrect syntax near '('.mi lancia , ma non riesco a vedere alcun problema con la sintassi. Qualche idea?
Oliver

Oliver, su quale versione stai girando? Funziona così com'è per me nel 2008R2 e 2012.
Rob Garrison,

24

In SQL 2012 ottenere queste informazioni a livello di tabella è diventato deliziosamente semplice:

SQL Management Studio -> Fare clic con il pulsante destro del mouse su Db -> Report -> Report standard -> Utilizzo del disco per tabella!

Godere


13
EXEC sp_MSforeachtable @command1="EXEC sp_spaceused '?'"

3
Se inserisci codice, XML o campioni di dati, PER FAVORE evidenzia quelle righe nell'editor di testo e fai clic sul pulsante "esempi di codice" ( { }) sulla barra degli strumenti dell'editor per formattarlo correttamente e evidenziarlo con la sintassi!
marc_s

4

Ecco la versione più compatta della risposta di maggior successo:

create table #tbl(
  name nvarchar(128),
  rows varchar(50),
  reserved varchar(50),
  data varchar(50),
  index_size varchar(50),
  unused varchar(50)
)

exec sp_msforeachtable 'insert into #tbl exec sp_spaceused [?]'

select * from #tbl
    order by convert(int, substring(data, 1, len(data)-3)) desc

drop table #tbl

4
--Gets the size of each index for the specified table
DECLARE @TableName sysname = N'SomeTable';

SELECT i.name AS IndexName
      ,8 * SUM(s.used_page_count) AS IndexSizeKB
FROM sys.indexes AS i
    INNER JOIN sys.dm_db_partition_stats AS s 
        ON i.[object_id] = s.[object_id] AND i.index_id = s.index_id
WHERE s.[object_id] = OBJECT_ID(@TableName, N'U')
GROUP BY i.name
ORDER BY i.name;

SELECT i.name AS IndexName
      ,8 * SUM(a.used_pages) AS IndexSizeKB
FROM sys.indexes AS i
    INNER JOIN sys.partitions AS p 
        ON i.[object_id]  = p.[object_id] AND i.index_id = p.index_id
    INNER JOIN sys.allocation_units AS a 
        ON p.partition_id = a.container_id
WHERE i.[object_id] = OBJECT_ID(@TableName, N'U')
GROUP BY i.name
ORDER BY i.name;

3

è passato molto tempo dalla creazione di questo post ma volevo condividere il mio script:

WITH CteIndex
AS
(
SELECT 
     reservedpages = (reserved_page_count)
     ,usedpages = (used_page_count)
     ,pages = (
            CASE
                WHEN (s.index_id < 2) THEN (in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count)
                ELSE lob_used_page_count + row_overflow_used_page_count
            END
            )    
     ,s.object_id   
     ,i.index_id        
     ,i.type_desc AS IndexType
     ,i.name AS indexname
    FROM sys.dm_db_partition_stats s
    INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id   
)
SELECT DISTINCT
DB_NAME(DB_ID()) AS DatabaseName
,o.name AS TableName
,o.object_id
,ct.indexname
,ct.IndexType
,ct.index_id
, IndexSpace = LTRIM (STR ((CASE WHEN usedpages > pages THEN CASE WHEN ct.index_id < 2 THEN  pages ELSE (usedpages - pages) END ELSE 0 END) * 8, 15, 0) + ' KB')
FROM CteIndex ct
INNER JOIN sys.objects o ON o.object_id = ct.object_id
INNER JOIN sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL , NULL) ps ON ps.object_id = o.object_id
AND ps.index_id = ct.index_id
ORDER BY name ASC

funziona per:

  • SQL Server (a partire dal 2008)
  • Include informazioni per tutte le tabelle per database corrente

0

Esiste una stored procedure estesa sp_spaceusedche consente di ottenere queste informazioni. È abbastanza complicato farlo dal dizionario dei dati, ma questo collegamento si apre a uno script che lo fa. Questa domanda sull'overflow dello stack ha alcune informazioni a ventaglio sulle strutture di dati sottostanti che puoi utilizzare per costruire stime delle dimensioni di tabelle e indici per la pianificazione della capacità.


0

Questa domanda deriva da altre due risposte:

Ottieni la dimensione di tutte le tabelle nel database

Come trovare gli oggetti più grandi in un database di SQL Server?

, ma l'ho migliorato per renderlo universale. Usa il sys.objectsdizionario:

SELECT 
    s.NAME as SCHEMA_NAME,
    t.NAME AS OBJ_NAME,
    t.type_desc as OBJ_TYPE,
    i.name as indexName,
    sum(p.rows) as RowCounts,
    sum(a.total_pages) as TotalPages, 
    sum(a.used_pages) as UsedPages, 
    sum(a.data_pages) as DataPages,
    (sum(a.total_pages) * 8) / 1024 as TotalSpaceMB, 
    (sum(a.used_pages) * 8) / 1024 as UsedSpaceMB, 
    (sum(a.data_pages) * 8) / 1024 as DataSpaceMB
FROM 
    sys.objects t
INNER JOIN
    sys.schemas s ON t.SCHEMA_ID = s.SCHEMA_ID 
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
WHERE 
    t.NAME NOT LIKE 'dt%' AND
    i.OBJECT_ID > 255 AND   
    i.index_id <= 1
GROUP BY 
    s.NAME, t.NAME, t.type_desc, i.object_id, i.index_id, i.name 
ORDER BY
    sum(a.total_pages) DESC
;

0

Per visualizzare i dati di archiviazione di una singola tabella (e dei relativi indici):

exec sp_spaceused MyTable
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.