Получить размер всех таблиц в базе данных

1271

Я унаследовал довольно большую базу данных SQL Server. Кажется, он занимает больше места, чем я ожидал, учитывая содержащиеся в нем данные.

Есть ли простой способ определить, сколько места на диске занимает каждая таблица?

Эрик
источник
к каким ролям у вас есть доступ? Являетесь ли вы администратором баз данных, или это управляется через веб-хостинг, клиент или подобное?
Роб Аллен
возможный дубликат размера таблицы и индекса в SQL Server
Джо Стефанелли
@RobAllen У меня есть полный доступ к базе данных, поэтому достаточно сценария, требующего любой роли.
Эрик
Для Azure я использовал этот
IRF

Ответы:

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
источник
7
Глупый вопрос, но возможно ли, что этот запрос может вызвать блокировку строки?
GEMI
7
Индексы также используют пространство, и объем пространства, используемого индексами, можно найти с помощью этого запроса ниже.
Йенс Фрэндсен
6
В вашем скрипте есть проблемы с отфильтрованными индексами: для каждого отфильтрованного индекса для данной таблицы я вижу дополнительную строку с именем этой таблицы в результатах. «RowCounts» каждой из этих дополнительных строк соответствует количеству строк, охватываемых одним из отфильтрованных индексов. (на Sql2012)
Акос Лукач
37
@ Тодд: некоторые люди хотят, чтобы все было так, а другие - по имени таблицы - сделайте свой выбор, измените код по мере необходимости ....
marc_s
12
Если ваши таблицы разделены, они появляются несколько раз без каких-либо указаний на то, что происходит. Вы можете либо добавить p.partition_number в список выбора, либо вы можете SUM (p.Rows) и удалить его из группы с помощью.
PRMan
561

Если вы используете SQL Server Management Studio (SSMS), вместо выполнения запроса ( который в моем случае возвратил повторяющиеся строки ) вы можете запустить стандартный отчет

  1. Щелкните правой кнопкой мыши на базе данных
  2. Перейдите в Отчеты> Стандартные отчеты> Использование диска по таблице

Примечание. Для корректной работы уровень совместимости базы данных должен быть равен 90 или выше. См. Http://msdn.microsoft.com/en-gb/library/bb510680.aspx

Кевин Брайдон
источник
54
В Management Studio 2012 вы можете сделать следующее: View-Object Explorer Details (F7) и перейти к «Таблицам» в Object Explorer. В деталях щелкните правой кнопкой мыши заголовок и выберите размер столбцов.
ValGe
3
за совет по новым функциям в SSMS 2012. Для нас, стариков, у нас никогда не было этой возможности. Так что мы просто сделали это по-старому TSQL :)
GoldBishop
3
Верьте или нет, иногда простые смертные (разработчики) хотели бы видеть эту информацию, и у нас нет прав на использование встроенного отчета, но мы можем запустить TSQL в принятом ответе. :) К вашему сведению (кстати, я все еще проголосовал за ваш ответ)
Эндрю
8
Похоже, отсутствует в Azure SQL :-(
Simon_Weaver
1
Я знаю, что это несерьезно, но, пожалуйста, вы просто отталкиваете маргинализированные группы от инженерных и технических, когда эти рассуждения повторяются повсюду. Вы должны изучить оба, но не должны наказывать людей за то, что они используют утилиты, экономящие время, чтобы работать умнее и быстрее. (Хотя SSMS иногда кажется «замедляющей утилитой» ...: X) Лично показания табличных данных обычно более понятны в графическом интерфейсе, хотя встроенные в Microsoft инструменты обычно являются исключениями для всего, что связано с пользовательским интерфейсом.
Джулия Макгиган
102

sp_spaceused может получить информацию о дисковом пространстве, используемом таблицей, индексированным представлением или всей базой данных.

Например:

USE MyDatabase; GO

EXEC sp_spaceused N'User.ContactInfo'; GO

Это сообщает информацию об использовании диска для таблицы ContactInfo.

Чтобы использовать это для всех таблиц одновременно:

USE MyDatabase; GO

sp_msforeachtable 'EXEC sp_spaceused [?]' GO

Вы также можете получить информацию об использовании диска, щелкнув правой кнопкой мыши функцию Стандартные отчеты SQL Server. Чтобы добраться до этого отчета, перейдите от объекта сервера в обозревателе объектов, перейдите к объекту Базы данных и щелкните правой кнопкой мыши любую базу данных. В появившемся меню выберите «Отчеты», затем «Стандартные отчеты», а затем «Использование диска по разделам: [DatabaseName]».

ось
источник
3
Это sp_msforeachtableудобно, хотя использование в SSMS может легко вызвать a, System.OutOfMemoryExceptionесли у вас большое количество таблиц, поэтому лучше использовать временную таблицу для хранения результатов.
syneticon-dj
1
Основная проблема, которую я вижу в sp_spacedused, заключается в том, что он возвращает данные в удобочитаемом формате (например, в столбце «зарезервировано» в моем случае «152 КБ»). Я предполагаю, что это переключится на MB / GB в зависимости от ситуации. Это очевидно полезно во многих ситуациях, но не в том случае, если вам нужно применить некоторую логику, основанную на размере, или вы хотите сравнить значения или что-то еще. Я искал способ выключить это, но я не мог определить один (я использую SQL Server 2005 :()
DarthPablo
55

Вот еще один метод: с помощью SQL Server Management Studio в обозревателе объектов перейдите в базу данных и выберите « Таблицы».

введите описание изображения здесь

Затем откройте Object Explorer Details (либо нажав F7, либо перейдите в View-> Object Explorer Details ). На странице сведений об обозревателе объектов щелкните правой кнопкой мыши заголовок столбца и включите столбцы, которые вы хотели бы видеть на странице. Вы также можете отсортировать данные по любому столбцу.

введите описание изображения здесь

Воробей
источник
Да, в SSMS в Azure отсутствуют некоторые функции по сравнению с локальной версией.
Воробей
@batmaci Не уверен, что это вообще сработало, когда вы комментировали базы данных SQL Azure, но, по-видимому, сейчас оно по крайней мере частично работает в последних версиях SSMS. Для меня кажется, что запрос метаданных таблицы истекает по времени, но перед этим он, похоже, возвращает несколько (3-10) таблиц, включая (надежно) выбранную таблицу. Выберите таблицу и нажмите «Обновить», чтобы увидеть нужную таблицу, если она не отображается.
pcdev
Azure не является «настоящим» SQL Server (ха-ха)
Обратный инженер
Я использовал это для Azure, благодаря с а (плюс один),
МАФ
Вы также можете экспортировать список в файл CSV с помощью утилиты, такой как NirSoft SysExporter: nirsoft.net/utils/sysexp.html
Макс
39

После некоторых поисков я не смог найти простой способ получить информацию по всем таблицам. Существует удобная хранимая процедура с именем sp_spaceused, которая будет возвращать все пространство, используемое базой данных. Если ему предоставляется имя таблицы, он возвращает пространство, используемое этой таблицей. Однако результаты, возвращаемые хранимой процедурой, не подлежат сортировке, поскольку столбцы являются символьными значениями.

Следующий скрипт сгенерирует информацию, которую я ищу.

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
Эрик
источник
После просмотра вышесказанного с использованием foreach и SP собирался написать что-то вроде этого, рад, что прокрутил страницу вниз, чтобы увидеть, что это сэкономило мне немного времени.
Брэд
37
 exec  sp_spaceused N'dbo.MyTable'

Для всех таблиц используйте .. (добавление из комментариев Павла)

exec sp_MSForEachTable 'exec sp_spaceused [?]'
Ройи Намир
источник
5
Подлый - вы изменили, из exec sp_helpdbкоторого ничего не отображается в таблицах, для exec sp_spaceusedчего - но только для одной таблицы за раз ... это не дает вам представление о том, какие таблицы у вас есть, сколько у них строк и как много места они занимают.
marc_s
4
exec sp_MSForEachTable 'exec sp_spaceused [?]'
Пол
27

Приведенные выше запросы хороши для определения объема пространства, используемого таблицей (включая индексы), но если вы хотите сравнить, сколько места используется индексами в таблице, используйте этот запрос:

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
Йенс Франдсен
источник
По какой причине суммирование столбца Indexsize (KB) для конкретной таблицы не согласуется с index_size из sp_spaceused?
Дерек
@Derek Исправил свой ответ, добавив where [i].[is_primary_key] = 0. Теперь размеры должны совпадать.
CodeAngry
Спасибо, но на самом деле это тоже не работает. У меня есть (очень маленькая) тестовая база данных, в интересующей таблице есть два индекса - первичный кластеризованный индекс в одном столбце и некластеризованный индекс в двух других столбцах. Этот запрос говорит, что каждый из них использует 16 КБ, но sp_spaceused говорит, что общее использование индекса составляет 24 КБ. Часть моей путаницы заключается в следующем: сравнивая этот запрос с «UsedSpaceKB» принятого ответа, я не вижу реальной разницы. То же самое, просто отсутствует добавление sys.tables. Я что-то упустил, или этот запрос по своей сути нарушен?
Дерек
У меня большие базы данных. И размеры соответствуют sp_spaceused. Я измеряю гигабайты, так что несколько мег не совпадают, не так много. Меня не волнуют точные размеры, просто идея.
CodeAngry
14

Если вам нужно рассчитать точно такие же числа, которые находятся на странице «Свойства таблицы - хранилище» в SSMS, вам нужно подсчитать их тем же методом, что и в SSMS (работает для SQL Server 2005 и выше ..., а также работает правильно для таблиц с полями больших объектов - потому что просто подсчет «used_pages» не позволяет точно определить размер индекса):

;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
источник
14

Расширение @xav ответит, что обрабатывает разделы таблицы, чтобы получить размер в МБ и ГБ. Протестировано на SQL Server 2008/2012 (прокомментировал строку где 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
Сантошкумар КБ
источник
также лучше порядок сортировки.
Pxtl
Это должен быть главный ответ.
Baodad
14

Для Azure я использовал это:

Вы должны иметь SSMS v17.x

Я использовал;

введите описание изображения здесь

С этим, как упомянул пользователь Воробей :

Откройте Databases> и выберите Таблицы ,
затем нажмите клавишу F7. Вы должны увидеть row count
как: введите описание изображения здесь

SSMS здесь подключен к базам данных Azure

IRF
источник
3
F7 сильно недогружен.
cskwg
1
Я понятия не имел, что это существовало, мне немного стыдно за себя: p Спасибо!
lollancf37
Это проблема с таблицами, оптимизированными для памяти, (я только что проверил, увидев этот пост :)
Amirreza
11

Мы использовали разбиение таблиц и имели некоторые проблемы с запросами, представленными выше, из-за дублирования записей.

Для тех, кому это необходимо, вы можете найти под запросом SQL Server 2014 при создании отчета «Использование диска по таблице». Я предполагаю, что это также работает с предыдущими версиями SQL Server.

Работает как часы.

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
источник
Спасибо за скрипт, который соответствует тому, как это делает SSMS, и правильно обрабатывает разделы.
Майк
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
отметка
источник
8

Небольшое изменение в ответе Mar_c , так как я возвращался на эту страницу так часто, по заказу первой строки большинства:

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 
Джоэл Харкс
источник
5

Это даст вам размеры и количество записей для каждой таблицы.

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
Уильям Уолсет
источник
2
Если вы публикуете код, XML или образцы данных, ПОЖАЛУЙСТА, выделите эти строки в текстовом редакторе и нажмите кнопку «примеры кода» ( { }) на панели инструментов редактора, чтобы красиво отформатировать и выделить синтаксис!
marc_s
4

Для получения всех размеров таблицы в одной базе данных вы можете использовать этот запрос:

Exec sys.sp_MSforeachtable ' sp_spaceused "?" '

И вы можете изменить его, чтобы вставить все результаты в временную таблицу и после этого выбрать из временной таблицы.

Insert into #TempTable Exec sys.sp_MSforeachtable ' sp_spaceused "?" ' 
Select * from #TempTable
Ардалан Шахголи
источник
3

Из командной строки с использованием OSQL :

OSQL -E -d <*databasename*> -Q "exec sp_msforeachtable 'sp_spaceused [?]'" > result.txt
user4658783
источник
3

Вот способ быстро получить размеры всех таблиц с помощью следующих шагов:

  1. Напишите данные команды T-SQL, чтобы получить список всех таблиц базы данных:

    select 'exec sp_spaceused ' + TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'
  2. Теперь скопируйте список таблиц базы данных и скопируйте его в новое окно анализатора запросов.

    exec sp_spaceused table1
    exec sp_spaceused table2
    exec sp_spaceused table3
    exec sp_spaceused table4
    exec sp_spaceused table5
  3. В анализаторе запросов SQL выберите из верхней панели инструментов параметр « Результаты в файл» ( Ctrl+ Shift+ F).

  4. Теперь, наконец, нажмите кнопку « Выполнить» , отмеченную красным цветом на панели инструментов .

  5. Размер базы данных всех таблиц теперь хранится в файле на вашем компьютере.

    Введите описание изображения здесь

Анжан Кант
источник
2

Я добавил еще несколько столбцов поверх ответа 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
Алан Кардосо
источник
1

Мой пост имеет отношение только к SQL Server 2000 и был протестирован для работы в моей среде.

Этот код обращается ко всем возможным базам данных одного экземпляра , а не только к одной.

Я использую две временные таблицы, чтобы помочь собрать соответствующие данные, а затем вывести результаты в одну «живую» таблицу.

Возвращаемые данные: DatabaseName, DatabaseTableName, Rows (в таблице), данные (размер таблицы в килобайтах может показаться), входные данные (я считаю, что это полезно знать, когда я последний раз запускал скрипт).

Недостатком этого кода является то, что поле «data» не хранится как int (символы «KB» хранятся в этом поле), и это будет полезно (но не обязательно) для сортировки.

Надеюсь, этот код поможет кому-то и сэкономит время!

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] 

Если вам нужно знать, таблица rsp_DatabaseTableSizes была создана с помощью:

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

GO
Эндрю
источник
1

Как простое расширение для ответа marc_s (который был принят), он настроен так, чтобы возвращать количество столбцов и разрешать фильтрацию:

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
Зак Смит
источник
После того, как вы присоединились к таблице Columns, у вас больше нет нужного табличного пространства. Внешнее применение будет исправлением.
dreamca4er
0

Обращаясь к ответу @Mark выше, добавил @ updateusage = 'true', чтобы принудительно установить статистику последних размеров ( 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
Крис Смит
источник
0

Вот пример запроса для получения таблиц размером более 1 ГБ в порядке убывания размера.

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
Сергей
источник