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

1271

Heredé una base de datos bastante grande de SQL Server. Parece ocupar más espacio de lo que esperaría, dados los datos que contiene.

¿Hay una manera fácil de determinar cuánto espacio en el disco está consumiendo cada tabla?

Eric
fuente
¿A qué roles tiene acceso? ¿Eres el DBA o se gestiona a través de un servidor web, cliente o similar?
Rob Allen
posible duplicado del tamaño
Joe Stefanelli
@RobAllen Tengo acceso completo a la base de datos, por lo que un script que requiere cualquier función es suficiente.
Eric
Para Azure utilicé esto
Irf

Respuestas:

2594
SELECT 
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows,
    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 
    TotalSpaceMB DESC, t.Name
marc_s
fuente
77
Pregunta tonta, pero ¿es posible que esta consulta pueda causar el bloqueo de filas?
GEMI
77
Los índices también usan espacio, y la cantidad de espacio utilizado por los índices se puede encontrar con esta consulta a continuación.
Jens Frandsen
66
Su secuencia de comandos tiene problemas con los índices filtrados: para cada índice filtrado de una tabla determinada, veo una fila adicional con el nombre de las tablas en los resultados. Los "RowCounts" de cada una de esas filas adicionales corresponden al número de filas cubiertas por uno de los índices filtrados. (en Sql2012)
Akos Lukacs
37
@Todd: algunas personas quieren que ordenó esa manera - que otros quieren que el nombre de la mesa - una serie de opciones, adaptar el código según sea necesario ....
marc_s
12
Si sus tablas están particionadas, se muestran varias veces sin ninguna indicación de lo que está sucediendo. Puede agregar p.partition_number a la lista de selección o puede SUMAR (p.Rows) y eliminarlo del grupo por.
PRMan
561

Si está utilizando SQL Server Management Studio (SSMS), en lugar de ejecutar una consulta ( que en mi caso devolvió filas duplicadas ) puede ejecutar un informe estándar

  1. Haga clic derecho en la base de datos
  2. Vaya a Informes> Informes estándar> Uso de disco por tabla

Nota: El nivel de compatibilidad de la base de datos debe establecerse en 90 o más para que esto funcione correctamente. Ver http://msdn.microsoft.com/en-gb/library/bb510680.aspx

Kevin Brydon
fuente
54
En Management Studio 2012 puede hacer: Ver detalles del Explorador de objetos (F7) y navegar a "Tablas" en el Explorador de objetos. En Detalles, haga clic con el botón derecho en el encabezado y seleccione columnas de tamaño.
ValGe
3
para aconsejar nuevas funcionalidades con SSMS 2012. Para nosotros, los viejos, nunca tuvimos esto disponible. Así que lo hicimos a la antigua manera TSQL :)
GoldBishop
3
Lo creas o no, a veces los simples mortales (desarrolladores) desean ver esta información y no tenemos permisos para usar el informe incorporado, pero podemos ejecutar el TSQL en la respuesta aceptada. :) Para su información (por cierto, todavía voté por su respuesta)
Andrew Steitz
8
No parece estar presente en Azure SQL :-(
Simon_Weaver
1
Sé que no es serio, pero, por favor, simplemente alejas a los grupos marginados de la ingeniería y la tecnología con esta línea de razonamiento que se repite en todas partes. Debes aprender ambos, pero tampoco debes castigar a las personas por usar utilidades que ahorran tiempo para trabajar de manera más inteligente y más rápida. (Aunque SSMS parece ser una "utilidad de ralentización" a veces ...: X) Personalmente, las lecturas de datos tabulares suelen ser más claras en una GUI, aunque las herramientas creadas por Microsoft tienden a ser la excepción para todo lo relacionado con la interfaz de usuario.
Julia McGuigan
102

sp_spaceused puede obtener información sobre el espacio en disco utilizado por una tabla, vista indizada o toda la base de datos.

Por ejemplo:

USE MyDatabase; GO

EXEC sp_spaceused N'User.ContactInfo'; GO

Esto informa la información de uso del disco para la tabla ContactInfo.

Para usar esto para todas las tablas a la vez:

USE MyDatabase; GO

sp_msforeachtable 'EXEC sp_spaceused [?]' GO

También puede obtener el uso del disco desde la funcionalidad de Informes estándar de clic derecho de SQL Server. Para llegar a este informe, navegue desde el objeto del servidor en el Explorador de objetos, baje al objeto Bases de datos y luego haga clic con el botón derecho en cualquier base de datos. En el menú que aparece, seleccione Informes, luego Informes estándar y luego "Uso del disco por partición: [Nombre de la base de datos]".

Eje
fuente
3
Esto es bueno, aunque el uso de sp_msforeachtableen SSMS puede desencadenar fácilmente System.OutOfMemoryExceptionsi tiene una gran cantidad de tablas, por lo que podría ser una mejor idea usar una tabla temporal para almacenar los resultados.
syneticon-dj
1
El principal problema que puedo ver con sp_spacedused es que parece devolver los datos en formato legible para humanos (por ejemplo, en la columna 'reservado' en mi caso tenía '152 KB'). Supongo que esto cambiará a MB / GB según corresponda. Esto es claramente útil en muchas situaciones, pero no si necesita aplicar alguna lógica basada en el tamaño, o si desea comparar valores o lo que sea. Busqué una forma de desactivarlo, pero no pude detectar uno (estoy usando SQL Server 2005 :()
DarthPablo
55

Aquí hay otro método: usando SQL Server Management Studio , en Object Explorer , vaya a su base de datos y seleccione Tablas

ingrese la descripción de la imagen aquí

Luego abra los Detalles del Explorador de objetos (ya sea presionando F7 o yendo a Ver-> Detalles del Explorador de objetos ). En la página de detalles del explorador de objetos, haga clic derecho en el encabezado de la columna y habilite las columnas que le gustaría ver en la página. También puede ordenar los datos por cualquier columna.

ingrese la descripción de la imagen aquí

Gorrión
fuente
Sí, SSMS en Azure carece de algunas características en comparación con la versión local.
Gorrión
@batmaci No estoy seguro de si esto funcionaba en absoluto cuando hizo su comentario sobre las bases de datos SQL de Azure, pero parece que ahora al menos funciona parcialmente en las versiones recientes de SSMS. Para mí, parece que la consulta para los metadatos de la tabla está agotando el tiempo de espera, pero antes de que lo haga, parece devolver unas pocas (3-10) tablas, incluida (de manera confiable) la tabla seleccionada. Seleccione una tabla y haga clic en actualizar para ver la tabla que desea si no se muestra.
pcdev
Azure no es SQL Server "real" (ja, ja)
Ingeniero invertido
He utilizado este para Azure, gracias con un (más uno),
Irf
También puede exportar la lista en un archivo CSV utilizando una utilidad como NirSoft SysExporter: nirsoft.net/utils/sysexp.html
Max
39

Después de algunas búsquedas, no pude encontrar una manera fácil de obtener información sobre todas las tablas. Hay un útil procedimiento almacenado llamado sp_spaceused que devolverá todo el espacio utilizado por la base de datos. Si se le proporciona un nombre de tabla, devuelve el espacio utilizado por esa tabla. Sin embargo, los resultados devueltos por el procedimiento almacenado no se pueden ordenar, ya que las columnas son valores de caracteres.

El siguiente script generará la información que estoy buscando.

create table #TableSize (
    Name varchar(255),
    [rows] int,
    reserved varchar(255),
    data varchar(255),
    index_size varchar(255),
    unused varchar(255))
create table #ConvertedSizes (
    Name varchar(255),
    [rows] int,
    reservedKb int,
    dataKb int,
    reservedIndexSize int,
    reservedUnused int)

EXEC sp_MSforeachtable @command1="insert into #TableSize
EXEC sp_spaceused '?'"
insert into #ConvertedSizes (Name, [rows], reservedKb, dataKb, reservedIndexSize, reservedUnused)
select name, [rows], 
SUBSTRING(reserved, 0, LEN(reserved)-2), 
SUBSTRING(data, 0, LEN(data)-2), 
SUBSTRING(index_size, 0, LEN(index_size)-2), 
SUBSTRING(unused, 0, LEN(unused)-2)
from #TableSize

select * from #ConvertedSizes
order by reservedKb desc

drop table #TableSize
drop table #ConvertedSizes
Eric
fuente
Después de ver lo anterior usando el foreach y el SP iba ​​a escribir algo como esto, me alegro de haberme desplazado hacia abajo para ver que me ahorró un poco de tiempo.
Brad
37
 exec  sp_spaceused N'dbo.MyTable'

Para todas las tablas, use .. (agregando de los comentarios de Paul)

exec sp_MSForEachTable 'exec sp_spaceused [?]'
Royi Namir
fuente
55
Disimulado : cambió de exec sp_helpdblo que no muestra nada sobre tablas, a lo exec sp_spaceusedque sí lo hace, pero solo para una tabla a la vez ... no le da una visión general de qué tablas tiene y cuántas filas tienen y cómo mucho espacio que ocupan.
marc_s
44
exec sp_MSForEachTable 'exec sp_spaceused [?]'
Paul
27

Las consultas anteriores son buenas para encontrar la cantidad de espacio utilizado por la tabla (incluidos los índices), pero si desea comparar cuánto espacio utilizan los índices en la tabla, utilice esta consulta:

SELECT
    OBJECT_NAME(i.OBJECT_ID) AS TableName,
    i.name AS IndexName,
    i.index_id AS IndexID,
    8 * SUM(a.used_pages) AS 'Indexsize(KB)'
FROM
    sys.indexes AS i
    JOIN sys.partitions AS p ON p.OBJECT_ID = i.OBJECT_ID AND p.index_id = i.index_id
    JOIN sys.allocation_units AS a ON a.container_id = p.partition_id
WHERE
    i.is_primary_key = 0 -- fix for size discrepancy
GROUP BY
    i.OBJECT_ID,
    i.index_id,
    i.name
ORDER BY
    OBJECT_NAME(i.OBJECT_ID),
    i.index_id
Jens Frandsen
fuente
¿Cuál es la razón por la que resumir la columna Indexsize (KB) para una tabla en particular no está de acuerdo con index_size de sp_spaceused?
Derek
@Derek Corrigió su respuesta agregando where [i].[is_primary_key] = 0. Ahora los tamaños deben coincidir.
CodeAngry
Gracias, pero esto tampoco está funcionando. Tengo una base de datos de prueba (muy pequeña), la tabla de interés tiene dos índices: un índice agrupado primario en una columna y un índice no agrupado en dos de las otras columnas. Esta consulta dice que cada uno de ellos usa 16kB, pero sp_spaceused dice que el uso total del índice es de 24kB. Parte de mi confusión es esta: al comparar esta consulta con el "UsedSpaceKB" de la respuesta aceptada, no veo una diferencia real. Misma unión, solo falta la adición de sys.tables. ¿Me estoy perdiendo algo o esta consulta está inherentemente rota?
Derek
Tengo grandes bases de datos. Y los tamaños coinciden con sp_spaceused. Mido los GB, por lo que unos pocos megas no coinciden no es mucho. No me importan los tamaños exactos, solo una idea.
CodeAngry
14

Si necesita calcular exactamente los mismos números, que están en la página 'propiedades de tabla - almacenamiento' en SSMS, debe contarlos con el mismo método que en SSMS (funciona para SQL Server 2005 y superior ... y también funciona correctamente para tablas con campos LOB, porque solo contar "páginas_utilizadas" no es suficiente para mostrar un tamaño de índice preciso):

;with cte as (
SELECT
t.name as TableName,
SUM (s.used_page_count) as used_pages_count,
SUM (CASE
            WHEN (i.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) as pages
FROM sys.dm_db_partition_stats  AS s 
JOIN sys.tables AS t ON s.object_id = t.object_id
JOIN sys.indexes AS i ON i.[object_id] = t.[object_id] AND s.index_id = i.index_id
GROUP BY t.name
)
select
    cte.TableName, 
    cast((cte.pages * 8.)/1024 as decimal(10,3)) as TableSizeInMB, 
    cast(((CASE WHEN cte.used_pages_count > cte.pages 
                THEN cte.used_pages_count - cte.pages
                ELSE 0 
          END) * 8./1024) as decimal(10,3)) as IndexSizeInMB
from cte
order by 2 desc
sqladmin
fuente
14

Extensión a la respuesta @xav que manejó las particiones de tabla para obtener el tamaño en MB y GB. Probado en SQL Server 2008/2012 (Comentó una línea donde is_memory_optimized = 1)

SELECT
    a2.name AS TableName,
    a1.rows as [RowCount],
    --(a1.reserved + ISNULL(a4.reserved,0)) * 8 AS ReservedSize_KB,
    --a1.data * 8 AS DataSize_KB,
    --(CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 AS IndexSize_KB,
    --(CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 AS UnusedSize_KB,
    CAST(ROUND(((a1.reserved + ISNULL(a4.reserved,0)) * 8) / 1024.00, 2) AS NUMERIC(36, 2)) AS ReservedSize_MB,
    CAST(ROUND(a1.data * 8 / 1024.00, 2) AS NUMERIC(36, 2)) AS DataSize_MB,
    CAST(ROUND((CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 / 1024.00, 2) AS NUMERIC(36, 2)) AS IndexSize_MB,
    CAST(ROUND((CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSize_MB,
    --'| |' Separator_MB_GB,
    CAST(ROUND(((a1.reserved + ISNULL(a4.reserved,0)) * 8) / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS ReservedSize_GB,
    CAST(ROUND(a1.data * 8 / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS DataSize_GB,
    CAST(ROUND((CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS IndexSize_GB,
    CAST(ROUND((CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 / 1024.00 / 1024.00, 2) AS NUMERIC(36, 2)) AS UnusedSize_GB
FROM
    (SELECT 
        ps.object_id,
        SUM (CASE WHEN (ps.index_id < 2) THEN row_count ELSE 0 END) AS [rows],
        SUM (ps.reserved_page_count) AS reserved,
        SUM (CASE
                WHEN (ps.index_id < 2) THEN (ps.in_row_data_page_count + ps.lob_used_page_count + ps.row_overflow_used_page_count)
                ELSE (ps.lob_used_page_count + ps.row_overflow_used_page_count)
            END
            ) AS data,
        SUM (ps.used_page_count) AS used
    FROM sys.dm_db_partition_stats ps
        --===Remove the following comment for SQL Server 2014+
        --WHERE ps.object_id NOT IN (SELECT object_id FROM sys.tables WHERE is_memory_optimized = 1)
    GROUP BY ps.object_id) AS a1
LEFT OUTER JOIN 
    (SELECT 
        it.parent_id,
        SUM(ps.reserved_page_count) AS reserved,
        SUM(ps.used_page_count) AS used
     FROM sys.dm_db_partition_stats ps
     INNER JOIN sys.internal_tables it ON (it.object_id = ps.object_id)
     WHERE it.internal_type IN (202,204)
     GROUP BY it.parent_id) AS a4 ON (a4.parent_id = a1.object_id)
INNER JOIN sys.all_objects a2  ON ( a1.object_id = a2.object_id ) 
INNER JOIN sys.schemas a3 ON (a2.schema_id = a3.schema_id)
WHERE a2.type <> N'S' and a2.type <> N'IT'
--AND a2.name = 'MyTable'       --Filter for specific table
--ORDER BY a3.name, a2.name
ORDER BY ReservedSize_MB DESC
Santhoshkumar KB
fuente
También mejor orden de clasificación.
Pxtl
Esta debería ser la mejor respuesta.
Baodad
14

Para Azure usé esto:

Debe tener SSMS v17.x

Solía;

ingrese la descripción de la imagen aquí

Con esto, como ha mencionado el usuario Sparrow :

Abra su Databases> y seleccione Tablas ,
luego presione la tecla F7 Debería ver row count
como: ingrese la descripción de la imagen aquí

SSMS aquí está conectado a bases de datos de Azure

Irf
fuente
3
F7 está muy infrautilizado.
cskwg
1
No tenía idea de que esto existía, estoy un poco avergonzado de mí mismo: p ¡Gracias!
lollancf37
Tiene un problema con las tablas de memoria optimizada, (acabo de probar después de ver esta publicación :)
Amirreza
11

Utilizamos particiones de tabla y tuvimos algunos problemas con las consultas proporcionadas anteriormente debido a registros duplicados.

Para aquellos que lo necesitan, puede encontrar debajo de la consulta que ejecuta SQL Server 2014 al generar el informe "Uso de disco por tabla". Supongo que también funciona con versiones anteriores de SQL Server.

Funciona a las mil maravillas.

SELECT
    a2.name AS [tablename],
    a1.rows as row_count,
    (a1.reserved + ISNULL(a4.reserved,0))* 8 AS reserved, 
    a1.data * 8 AS data,
    (CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data THEN (a1.used + ISNULL(a4.used,0)) - a1.data ELSE 0 END) * 8 AS index_size,
    (CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used ELSE 0 END) * 8 AS unused
FROM
    (SELECT 
        ps.object_id,
        SUM (
            CASE
                WHEN (ps.index_id < 2) THEN row_count
                ELSE 0
            END
            ) AS [rows],
        SUM (ps.reserved_page_count) AS reserved,
        SUM (
            CASE
                WHEN (ps.index_id < 2) THEN (ps.in_row_data_page_count + ps.lob_used_page_count + ps.row_overflow_used_page_count)
                ELSE (ps.lob_used_page_count + ps.row_overflow_used_page_count)
            END
            ) AS data,
        SUM (ps.used_page_count) AS used
    FROM sys.dm_db_partition_stats ps
        WHERE ps.object_id NOT IN (SELECT object_id FROM sys.tables WHERE is_memory_optimized = 1)
    GROUP BY ps.object_id) AS a1
LEFT OUTER JOIN 
    (SELECT 
        it.parent_id,
        SUM(ps.reserved_page_count) AS reserved,
        SUM(ps.used_page_count) AS used
     FROM sys.dm_db_partition_stats ps
     INNER JOIN sys.internal_tables it ON (it.object_id = ps.object_id)
     WHERE it.internal_type IN (202,204)
     GROUP BY it.parent_id) AS a4 ON (a4.parent_id = a1.object_id)
INNER JOIN sys.all_objects a2  ON ( a1.object_id = a2.object_id ) 
INNER JOIN sys.schemas a3 ON (a2.schema_id = a3.schema_id)
WHERE a2.type <> N'S' and a2.type <> N'IT'
ORDER BY a3.name, a2.name
xav
fuente
Gracias por un script que coincide con la forma en que SSMS lo hace y maneja las particiones correctamente.
Mike
8
-- Show the size of all the tables in a database sort by data size descending
SET NOCOUNT ON
DECLARE @TableInfo TABLE (tablename varchar(255), rowcounts int, reserved varchar(255), DATA varchar(255), index_size varchar(255), unused varchar(255))
DECLARE @cmd1 varchar(500)
SET @cmd1 = 'exec sp_spaceused ''?'''

INSERT INTO @TableInfo (tablename,rowcounts,reserved,DATA,index_size,unused)
EXEC sp_msforeachtable @command1=@cmd1

SELECT * FROM @TableInfo ORDER BY Convert(int,Replace(DATA,' KB','')) DESC
marca
fuente
8

Un pequeño cambio en la respuesta de Mar_c , ya que he estado volviendo a esta página con tanta frecuencia, ordenado por la mayoría de las primeras filas:

SELECT
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows AS RowCounts,
    SUM(a.total_pages) * 8 AS TotalSpaceKB,
    SUM(a.used_pages) * 8 AS UsedSpaceKB,
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
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
    --p.rows DESC --Uncomment to order by amount rows instead of size in KB.
    SUM(a.total_pages) DESC 
Joel Harkes
fuente
5

Esto le dará los tamaños y los recuentos de registros para cada tabla.

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
-- Get a list of tables and their sizes on disk
ALTER PROCEDURE [dbo].[sp_Table_Sizes]
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
DECLARE @table_name VARCHAR(500)  
DECLARE @schema_name VARCHAR(500)  
DECLARE @tab1 TABLE( 
        tablename VARCHAR (500) collate database_default 
       ,schemaname VARCHAR(500) collate database_default 
) 

CREATE TABLE #temp_Table ( 
        tablename sysname 
       ,row_count INT 
       ,reserved VARCHAR(50) collate database_default 
       ,data VARCHAR(50) collate database_default 
       ,index_size VARCHAR(50) collate database_default 
       ,unused VARCHAR(50) collate database_default  
) 

INSERT INTO @tab1  
SELECT Table_Name, Table_Schema  
FROM information_schema.tables  
WHERE TABLE_TYPE = 'BASE TABLE' 

DECLARE c1 CURSOR FOR 
SELECT Table_Schema + '.' + Table_Name   
FROM information_schema.tables t1  
WHERE TABLE_TYPE = 'BASE TABLE' 

OPEN c1 
FETCH NEXT FROM c1 INTO @table_name 
WHILE @@FETCH_STATUS = 0  
BEGIN   
        SET @table_name = REPLACE(@table_name, '[','');  
        SET @table_name = REPLACE(@table_name, ']','');  

        -- make sure the object exists before calling sp_spacedused 
        IF EXISTS(SELECT id FROM sysobjects WHERE id = OBJECT_ID(@table_name)) 
        BEGIN 
               INSERT INTO #temp_Table EXEC sp_spaceused @table_name, false; 
        END 

        FETCH NEXT FROM c1 INTO @table_name 
END 
CLOSE c1 
DEALLOCATE c1 

SELECT  t1.* 
       ,t2.schemaname  
FROM #temp_Table t1  
INNER JOIN @tab1 t2 ON (t1.tablename = t2.tablename ) 
ORDER BY schemaname,t1.tablename; 

DROP TABLE #temp_Table
END
William Walseth
fuente
2
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 dar formato y sintaxis.
marc_s
4

Para obtener todos los tamaños de tabla en una base de datos, puede usar esta consulta:

Exec sys.sp_MSforeachtable ' sp_spaceused "?" '

Y puede cambiarlo para insertar todo el resultado en la tabla temporal y luego seleccionarlo en la tabla temporal.

Insert into #TempTable Exec sys.sp_MSforeachtable ' sp_spaceused "?" ' 
Select * from #TempTable
Ardalan Shahgholi
fuente
3

Desde un símbolo del sistema con OSQL :

OSQL -E -d <*databasename*> -Q "exec sp_msforeachtable 'sp_spaceused [?]'" > result.txt
usuario4658783
fuente
3

Aquí hay una manera de obtener todos los tamaños de tablas rápidamente con los siguientes pasos:

  1. Escriba los comandos T-SQL dados para enumerar todas las tablas de la base de datos:

    select 'exec sp_spaceused ' + TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'
  2. Ahora copie la lista de tablas de la base de datos y cópiela en una nueva ventana del analizador de consultas

    exec sp_spaceused table1
    exec sp_spaceused table2
    exec sp_spaceused table3
    exec sp_spaceused table4
    exec sp_spaceused table5
  3. En el analizador de consultas SQL , seleccione de la opción de la barra de herramientas superior Resultados al archivo ( Ctrl+ Shift+F ).

  4. Ahora finalmente presione el botón Ejecutar rojo marcado en la barra de herramientas anterior .

  5. El tamaño de la base de datos de todas las tablas ahora se almacena en un archivo en su computadora.

    Ingrese la descripción de la imagen aquí

Anjan Kant
fuente
2

Agregué algunas columnas más sobre la respuesta de marc_s:

with fs
as
(
select i.object_id,
        p.rows AS RowCounts,
        SUM(a.total_pages) * 8 AS TotalSpaceKb
from     sys.indexes i 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 
    i.OBJECT_ID > 255 
GROUP BY 
    i.object_id,
    p.rows
)

SELECT 
    t.NAME AS TableName,
    fs.RowCounts,
    fs.TotalSpaceKb,
    t.create_date,
    t.modify_date,
    ( select COUNT(1)
        from sys.columns c 
        where c.object_id = t.object_id ) TotalColumns    
FROM 
    sys.tables t INNER JOIN      
    fs  ON t.OBJECT_ID = fs.object_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
ORDER BY 
    t.Name
Alan Cardoso
fuente
1

Mi publicación solo es relevante para SQL Server 2000 y se ha probado que funciona en mi entorno.

Este código accede a todas las bases de datos posibles de una sola instancia , no solo a una sola base de datos.

Utilizo dos tablas temporales para ayudar a recopilar los datos apropiados y luego volcar los resultados en una tabla 'En vivo'.

Los datos devueltos son: DatabaseName, DatabaseTableName, Filas (en la tabla), datos (el tamaño de la tabla en KB parecería), datos de entrada (lo encuentro útil para saber cuándo ejecuté el script por última vez).

La caída de este código es que el campo 'datos' no se almacena como un int (los caracteres 'KB' se mantienen en ese campo), y eso sería útil (pero no totalmente necesario) para la clasificación.

¡Ojalá este código ayude a alguien y les ahorre algo de tiempo!

CREATE PROCEDURE [dbo].[usp_getAllDBTableSizes]

AS
BEGIN
   SET NOCOUNT OFF

   CREATE TABLE #DatabaseTables([dbname] sysname,TableName sysname)
   CREATE TABLE #AllDatabaseTableSizes(Name sysname,[rows] VARCHAR(18), reserved VARCHAR(18), data VARCHAR(18), index_size VARCHAR(18), unused VARCHAR(18))

   DECLARE @SQL nvarchar(4000)
   SET @SQL='select ''?'' AS [Database], Table_Name from [?].information_schema.tables WHERE TABLE_TYPE = ''BASE TABLE'' '

   INSERT INTO #DatabaseTables(DbName, TableName)
      EXECUTE sp_msforeachdb @Command1=@SQL

   DECLARE AllDatabaseTables CURSOR LOCAL READ_ONLY FOR   
   SELECT TableName FROM #DatabaseTables

   DECLARE AllDatabaseNames CURSOR LOCAL READ_ONLY FOR   
   SELECT DBName FROM #DatabaseTables

   DECLARE @DBName sysname  
   OPEN AllDatabaseNames  

   DECLARE @TName sysname
   OPEN AllDatabaseTables  

   WHILE 1=1 BEGIN 
      FETCH NEXT FROM AllDatabaseNames INTO @DBName  
      FETCH NEXT FROM AllDatabaseTables INTO @TName 
      IF @@FETCH_STATUS<>0 BREAK  
      INSERT INTO #AllDatabaseTableSizes
         EXEC ( 'EXEC ' + @DBName + '.dbo.sp_spaceused ' + @TName) 

   END 

   --http://msdn.microsoft.com/en-us/library/aa175920(v=sql.80).aspx
   INSERT INTO rsp_DatabaseTableSizes (DatabaseName, name, [rows], data)
      SELECT   [dbname], name, [rows],  data FROM #DatabaseTables
      INNER JOIN #AllDatabaseTableSizes
      ON #DatabaseTables.TableName = #AllDatabaseTableSizes.Name
      GROUP BY [dbname] , name, [rows],  data
      ORDER BY [dbname]
   --To be honest, I have no idea what exact duplicates we are dropping
    -- but in my case a near enough approach has been good enough.
   DELETE FROM [rsp_DatabaseTableSizes]
   WHERE name IN 
      ( 
      SELECT name 
      FROM [rsp_DatabaseTableSizes]
      GROUP BY name
      HAVING COUNT(*) > 1
      )

   DROP TABLE #DatabaseTables
   DROP TABLE #AllDatabaseTableSizes

   CLOSE AllDatabaseTables  
   DEALLOCATE AllDatabaseTables  

   CLOSE AllDatabaseNames  
   DEALLOCATE AllDatabaseNames      
END

--EXEC [dbo].[usp_getAllDBTableSizes] 

En caso de que necesite saber, la tabla rsp_DatabaseTableSizes se creó a través de:

CREATE TABLE [dbo].[rsp_DatabaseSizes](
    [DatabaseName] [varchar](1000) NULL,
    [dbSize] [decimal](15, 2) NULL,
    [DateUpdated] [smalldatetime] NULL
) ON [PRIMARY]

GO
Andrés
fuente
1

Como una extensión simple a la respuesta de marc_s (la que ha sido aceptada), esto se ajusta para devolver el recuento de columnas y permitir el filtrado:

SELECT *
FROM
(

SELECT 
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows AS RowCounts,
    COUNT(DISTINCT c.COLUMN_NAME) as ColumnCount,
    SUM(a.total_pages) * 8 AS TotalSpaceKB, 
    (SUM(a.used_pages) * 8) AS UsedSpaceKB, 
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
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
INNER JOIN
    INFORMATION_SCHEMA.COLUMNS c ON t.NAME = c.TABLE_NAME
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
) AS Result

WHERE
    RowCounts > 1000
    AND ColumnCount > 10
ORDER BY 
    UsedSpaceKB DESC
Zach Smith
fuente
Después de unirse a la tabla Columnas, ya no tiene el espacio de tabla correcto. La aplicación externa será la solución.
dreamca4er
0

Refiriéndose a la respuesta de @Mark anterior, agregó @ updateusage = 'true' para forzar las últimas estadísticas de tamaño ( https://msdn.microsoft.com/en-us/library/ms188776.aspx ):

        SET NOCOUNT ON
        DECLARE @TableInfo TABLE (tablename varchar(255), rowcounts int, reserved varchar(255), DATA varchar(255), index_size varchar(255), unused varchar(255))
        DECLARE @cmd1 varchar(500)
        SET @cmd1 = 'exec sp_spaceused @objname =''?'', @updateusage =''true'' '

        INSERT INTO @TableInfo (tablename,rowcounts,reserved,DATA,index_size,unused)
        EXEC sp_msforeachtable @command1=@cmd1 
SELECT * FROM @TableInfo ORDER BY Convert(int,Replace(DATA,' KB','')) DESC
Chris Smith
fuente
0

Aquí hay una consulta de muestra para obtener tablas de más de 1 GB ordenadas por tamaño descendente.

USE YourDB
GO

DECLARE @Mult float = 8
SET @Mult = @Mult / POWER(2, 20) -- Use POWER(2, 10) for MBs

; WITH CTE AS
(
SELECT
    i.object_id,
    Rows = MAX(p.rows),
    TotalSpaceGB = ROUND(SUM(a.total_pages) * @Mult, 0),
    UsedSpaceGB = ROUND(SUM(a.used_pages) * @Mult, 0)
FROM 
    sys.indexes i
JOIN
    sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
JOIN
    sys.allocation_units a ON p.partition_id = a.container_id
WHERE
    i.object_id > 255
GROUP BY
    i.object_id
HAVING
    SUM(a.total_pages) * @Mult > 1
)
SELECT 
    SchemaName = s.name,
    TableName = t.name,
    c.TotalSpaceGB,
    c.UsedSpaceGB,
    UnusedSpaceGB = c.TotalSpaceGB - c.UsedSpaceGB,
    [RowCount] = c.Rows
FROM 
    CTE c
JOIN    
    sys.tables t ON t.object_id = c.object_id
JOIN
    sys.schemas s ON t.schema_id = s.schema_id
ORDER BY
    c.TotalSpaceGB DESC
Sergey
fuente