Tabela e tamanho do índice no SQL Server

90

Podemos ter uma consulta SQL que basicamente ajudará na visualização de tamanhos de tabelas e índices no SQl Server.

Como o servidor SQL mantém o uso de memória para tabelas / índices?

Kamal Joshi
fonte
1
Você também pode achar o procedimento armazenado sp_helpdbútil
Zack Burt
1
Há já responde a esta, mas eu pessoalmente usar a consulta neste link: qualityofdata.com/2011/02/02/...
naiem

Respostas:

73

O exec sp_spaceusedparâmetro sem mostra o resumo de todo o banco de dados. A solução foreachtable gera um conjunto de resultados por tabela - que o SSMS pode não ser capaz de lidar se você tiver muitas tabelas.

Criei um script que coleta as informações da tabela por meio sp_spaceusede exibe um resumo em um único conjunto de registros, classificado por tamanho.

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
Devio
fonte
4
Seu script lida apenas com tabelas no esquema 'dbo'. Se eu tiver uma tabela em meu banco de dados com um esquema de 'Auditoria', sp_spaceused precisa ser chamado assim: exec sp_spaceused 'Audit.Data'. Portanto, o script precisa ser modificado para alimentá-lo com o nome da tabela precedido pelo nome do esquema (separado por um ponto) para que ele retorne dados sobre tabelas de outros esquemas.
Baodad
1
Bom ponto, @Boadad ... isso deve ser uma solução super fácil. Substituir o "selecionar nome de sysobjects onde xtype = 'U'" por isso deve resolver: "select '[' + sc.name + ']. [' + S.name + ']' DE sysobjects s ​​INNER JOIN sys .schemas sc ON s.uid = sc.schema_id onde s.xtype = 'U' "Ótimo script, obrigado!
DCaugs de
em vez de usar uma tabela temporária, podemos inserir dados em outra tabela que não seja temporária?
Prabhakar
@PrabhakarPandey Claro, basta remover o #.
Racer SQL
120

sp_spaceused fornece o tamanho de todos os índices combinados.

Se você quiser o tamanho de cada índice de uma tabela, use uma destas duas consultas:

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

Os resultados geralmente são ligeiramente diferentes, mas dentro de 1%.

Rob Garrison
fonte
A primeira consulta inclui chaves primárias, o que é um pouco confuso por alguns motivos.
quillbreaker de
A segunda consulta joga Msg 102, Level 15, State 1, Line 5 - Incorrect syntax near '('.para mim, mas não consigo ver nenhum problema com a sintaxe. Qualquer ideia?
Oliver
Oliver, em qual versão você está rodando? Funciona como está para mim em 2008R2 e 2012.
Rob Garrison
24

No SQL 2012, obter essas informações em nível de tabela tornou-se deliciosamente simples:

SQL Management Studio -> Clique com o botão direito em Db -> Relatórios -> Relatórios padrão -> Uso de disco por tabela!

Aproveitar

Earthling42
fonte
13
EXEC sp_MSforeachtable @command1="EXEC sp_spaceused '?'"
Ben R
fonte
3
Se você postar código, XML ou amostras de dados, POR FAVOR destaque essas linhas no editor de texto e clique no botão "amostras de código" ( { }) na barra de ferramentas do editor para formatar bem e realçar a sintaxe!
marc_s
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;
Alex
fonte
3

Aqui está uma versão mais compacta da resposta de maior sucesso:

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
alpav
fonte
3

faz muito tempo desde a criação deste post, mas eu queria compartilhar meu roteiro:

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

funciona para:

  • SQL Server (começando em 2008)
  • Inclui informações para todas as tabelas por banco de dados atual
Jthalliens
fonte
0

Existe um procedimento armazenado estendido sp_spaceusedque obtém essas informações. É bastante complicado fazer isso a partir do dicionário de dados, mas este link se abre para um script que faz isso. Esta questão stackoverflow tem algumas informações sobre as estruturas de dados subjacentes que você pode usar para construir estimativas de tamanhos de tabela e índice para planejamento de capacidade.

ConcernedOfTunbridgeWells
fonte
0

Esta consulta vem de duas outras respostas:

Obtenha o tamanho de todas as tabelas no banco de dados

Como encontrar objetos maiores em um banco de dados SQL Server?

, mas eu aprimorei isso para ser universal. Ele usa sys.objectsdicionário:

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
;
Jakub P
fonte