Tamaño de tabla e índice en SQL Server

90

¿Podemos tener una consulta SQL que básicamente ayude a ver los tamaños de tabla e índice en SQl Server?

¿Cómo el servidor SQL mantiene el uso de la memoria para tablas / índices?

Kamal Joshi
fuente
1
También puede encontrar sp_helpdbútil el procedimiento almacenado
Zack Burt
1
Ya hay respuestas a esto, pero yo personalmente uso la consulta en este enlace: qualityofdata.com/2011/02/02/…
naiem

Respuestas:

73

El exec sp_spaceusedparámetro sin muestra el resumen de toda la base de datos. La solución foreachtable genera un conjunto de resultados por tabla, que es posible que SSMS no pueda manejar si tiene demasiadas tablas.

Creé un script que recopila la información de la tabla sp_spaceusedy muestra un resumen en un solo conjunto de registros, ordenados por tamaño.

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
fuente
4
Su secuencia de comandos solo maneja tablas en el esquema 'dbo'. Si tengo una tabla en mi base de datos con un esquema de 'Auditoría', sp_spaceused debe llamarse así: exec sp_spaceused 'Audit.Data'. Por lo tanto, el script debe modificarse para alimentarlo con el nombre de la tabla precedido por el nombre del esquema (separado por un punto) para que devuelva datos sobre tablas de otros esquemas.
Baodad
1
Buen punto @Boadad ... eso debería ser una solución súper fácil. Reemplazar el "nombre de selección de sysobjects donde xtype = 'U'" con esto debería funcionar: "seleccione '[' + sc.name + ']. [' + S.name + ']' FROM sysobjects s ​​INNER JOIN sys .schemas sc ON s.uid = sc.schema_id donde s.xtype = 'U' "¡Gran guión, gracias!
DCaugs
en lugar de usar una tabla temporal, ¿podemos insertar datos en otra tabla que no sea temporal?
Prabhakar
@PrabhakarPandey Claro que solo elimine el #.
Racer SQL
120

sp_spaceused le da el tamaño de todos los índices combinados.

Si desea el tamaño de cada índice para una tabla, use una de estas dos 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

Los resultados suelen ser ligeramente diferentes pero dentro del 1%.

Rob Garrison
fuente
La primera consulta incluye claves primarias, lo cual es un poco confuso por un par de razones.
Quillbreaker
La segunda consulta Msg 102, Level 15, State 1, Line 5 - Incorrect syntax near '('.me arroja , pero no veo ningún problema con la sintaxis. ¿Alguna idea?
Oliver
Oliver, ¿en qué versión estás corriendo? Funciona como está para mí en 2008R2 y 2012.
Rob Garrison
24

En SQL 2012, obtener esta información a nivel de tabla se ha vuelto deliciosamente simple:

SQL Management Studio -> Haga clic derecho en Db -> Informes -> Informes estándar -> Uso de disco por tabla.

Disfrutar

terrícola42
fuente
13
EXEC sp_MSforeachtable @command1="EXEC sp_spaceused '?'"
Ben R
fuente
3
Si publica muestras de código, XML o datos, POR FAVOR resalte esas líneas en el editor de texto y haga clic en el botón "Muestras de código" ( { }) en la barra de herramientas del editor para formatearlo y resaltarlo de forma agradable.
marc_s
4

Aquí hay una versión más compacta de la respuesta más exitosa:

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
fuente
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
fuente
3

Ha pasado mucho tiempo desde la creación de esta publicación, pero quería compartir mi guión:

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 (a partir de 2008)
  • Incluye información para todas las tablas por base de datos actual
jthalliens
fuente
0

Existe un procedimiento almacenado extendido sp_spaceusedque obtiene esta información. Es bastante complicado hacerlo desde el diccionario de datos, pero este enlace se abre a un script que lo hace. Esta pregunta de stackoverflow tiene información sobre las estructuras de datos subyacentes que puede utilizar para construir estimaciones de tamaños de tablas e índices para la planificación de la capacidad.

PreocupadoDeTunbridgeWells
fuente
0

Esta consulta proviene de otras dos respuestas:

Obtener el tamaño de todas las tablas en la base de datos

¿Cómo encontrar objetos más grandes en una base de datos de SQL Server?

, pero realcé esto para que sea universal. Utiliza sys.objectsdiccionario:

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
fuente