Отримайте розмір усіх таблиць у базі даних


1271

Я успадкував досить велику базу даних SQL Server. Здається, вона займає більше місця, ніж я б очікувала, враховуючи дані, які вона містить.

Чи є простий спосіб визначити, скільки місця на диску витрачає кожна таблиця?


до яких ролей ви маєте доступ? Ви DBA, чи цим керуєте через веб-хостинг, клієнт чи подібне?
Роб Аллен

можливий дублікат розміру таблиці та індексу на SQL Server
Джо Стефанеллі,

@RobAllen У мене є повний доступ до бази даних, тому сценарій, який вимагає будь-якої ролі, є достатнім.
Ерік


Для Azure я використав це
Ірф

Відповіді:


2593
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

7
Дурне питання, але чи можливо, що цей запит може призвести до блокування рядків?
GEMI

7
Індекси також використовують простір, і обсяг простору, який використовується індексами, можна знайти за допомогою цього запиту нижче.
Jens Frandsen

6
У вашому скрипті є проблеми з відфільтрованими індексами: для кожного відфільтрованого індексу для даної таблиці я бачу додатковий рядок із назвою цих таблиць у результатах. "Кількість рядків" кожного з цих додаткових рядків відповідає кількості рядків, охоплених одним з відфільтрованих індексів. (on Sql2012)
Akos

37
@Todd: деякі хочуть, щоб це було замовлено саме так - інші хочуть це за назвою таблиці - візьміть свій вибір,
адаптуйте

12
Якщо ваші таблиці розміщені в розділі, вони відображаються кілька разів без будь-якої вказівки, що відбувається. Ви можете додати p.partition_number до списку вибору, або ви можете SUM (p.Rows) та видалити його з групи.
PRMan

561

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

  1. Клацніть правою кнопкою миші на базі даних
  2. Перейдіть до Звіти> Стандартні звіти> Використання диска за таблицею

Примітка. Щоб нормально працювати, рівень сумісності баз даних повинен бути встановлений на 90 або вище. Дивіться http://msdn.microsoft.com/en-gb/library/bb510680.aspx


54
У програмі Management Studio 2012 ви можете зробити: Деталі провідника перегляду об’єктів (F7) та перейти до пункту «Таблиці» в Провіднику об’єктів. У подробицях клацніть правою кнопкою миші на заголовку та виберіть стовпці розміру.
ValGe

3
для консультування нових функціональних можливостей із SSMS 2012. Для нас, старих, ніколи такого не було в наявності. Тож ми просто зробили це старим способом TSQL :)
GoldBishop

3
Вірите чи ні, інколи просто смертні (розробники) хотіли б бачити цю інформацію, і у нас немає дозволів використовувати вбудований звіт, але ми можемо запустити TSQL у прийнятій відповіді. :) FYI (До речі, я все-таки підтримав вашу відповідь)
Ендрю Штайц,

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. Щоб дійти до цього звіту, перейдіть від об’єкта сервера в Провідник об’єктів, перейдіть до об’єкта Бази даних вниз і натисніть правою кнопкою миші будь-яку базу даних. У меню, яке з'явиться, виберіть Звіти, потім Стандартні звіти, а потім "Використання диска за розділом: [Ім'я бази даних]".


3
Це акуратно, хоча використання sp_msforeachtableSSMS легко може викликати a, System.OutOfMemoryExceptionякщо у вас є велика кількість таблиць, тому може бути кращою ідеєю використовувати тимчасову таблицю для зберігання результатів.
syneticon-dj

1
Основна проблема, яку я можу побачити з програмою sp_spacedused, полягає в тому, що, здається, повертаються дані у читаному для людини форматі (наприклад, у стовпці "зарезервований", у моєму випадку "152 КБ"). Я припускаю, що це перейде на МБ / ГБ у відповідних випадках. Це, очевидно, корисно у багатьох ситуаціях, але не, якщо вам потрібно застосувати певну логіку, виходячи з розміру, або хочете порівняти значення чи будь-що інше. Я шукав спосіб його вимкнути, але не зміг його помітити (я використовую SQL Server 2005 :()
DarthPablo

55

Ось ще один метод: використовуючи SQL Server Management Studio , в Провіднику об’єктів перейдіть до своєї бази даних та виберіть « Таблиці»

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

Потім відкрийте деталі провідника об’єктів (натисканням клавіші F7 або переходом до Перегляд-> Деталі провідника об’єкта ). На сторінці інформації про дослідник об’єкта клацніть правою кнопкою миші на заголовку стовпця та ввімкніть стовпці, які ви хочете бачити на сторінці. Ви також можете сортувати дані за будь-яким стовпцем.

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


Так, у SSMS у Azure відсутні деякі функції порівняно з локальною версією.
Воробей

@batmaci Не впевнений, чи це взагалі спрацювало, коли ви робили коментар щодо баз даних Azure SQL, але, здається, принаймні частково працюють зараз у останніх версіях SSMS. Мені здається, що запит щодо метаданих таблиць закінчується, але перед тим, як здається, повертається кілька (3-10) таблиць, що належать, включаючи (надійно) вибрану таблицю. Виберіть таблицю та натисніть оновити, щоб побачити потрібну таблицю, якщо вона не відображається.
pcdev

Лазур не є "справжнім" сервером SQL (ха-ха)
Engineer

Я використав це для 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, і СП збирався написати щось подібне, радий, що прокрутився вниз, побачивши, що це заощадило мені трохи часу.
Бред

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" (КБ) для певної таблиці не погоджується із розміром index_space від sp_spaceused?
Дерек

@Derek Виправив свою відповідь, додавши where [i].[is_primary_key] = 0. Тепер розміри повинні відповідати.
CodeAngry

Дякую, але і це насправді не виходить. У мене є (дуже невелика) база даних тестів, в цікавій таблиці є два індекси - первинний кластерний індекс на одному стовпчику та некластерний індекс у двох інших стовпцях. Цей запит говорить, що кожен з них використовує 16 кБ, але sp_spaceused каже, що загальне використання індексу становить 24 кБ. Частина моєї плутанини полягає в наступному: Порівнюючи цей запит із "UsedSpaceKB" прийнятої відповіді, я не бачу реальної різниці. Те саме приєднується, лише пропускаючи додавання sys.tables. Я щось пропускаю, або цей запит по суті порушений?
Дерек

У мене великі бази даних. І розміри відповідають sp_spaceused. Я вимірюю ГБ, так що кілька мег не збігаються - це не так багато. Мене не цікавлять точні розміри, просто ідея.
CodeAngry

14

Якщо вам потрібно обчислити абсолютно однакові числа, що знаходяться на сторінці "Властивості таблиці - зберігання" в SSMS, вам потрібно порахувати їх тим самим методом, що і в SSMS (працює для сервера sql 2005 і вище ... а також працює правильно для таблиць з полями LOB - тому що лише підрахунок "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

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

Це має бути головна відповідь.
Баодад

14

Для Azure я використав це:

У вас повинен бути SSMS v17.x

Я використав;

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

З цим, як згадував User Sparrow :

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

SSMS тут підключений до баз даних Azure


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

Дякуємо за сценарій, який відповідає тому, як це робить 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

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. Тепер нарешті натисніть на кнопку Execute червоною, позначеною на панелі інструментів вище .

  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 і перевірена на роботу в моєму середовищі.

Цей код отримує доступ до всіх можливих баз даних одного примірника , а не лише до однієї бази даних.

Я використовую дві таблиці темп, щоб допомогти зібрати відповідні дані, а потім скинути результати в одну таблицю "Live".

Повернуті дані: DatabaseName, DatabaseTableName, Рядки (у таблиці), дані (розмір таблиці в КБ, здавалося б), дані про введення (я вважаю це корисним для того, щоб знати, коли я востаннє виконував сценарій).

Пониження цього коду полягає в тому, що поле "дані" не зберігається як 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

Після того як ви приєдналися до таблиці стовпців, у вас більше немає потрібного простору для таблиці. Зовнішнє застосування буде виправлено.
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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.