Як ви можете визначити, які таблиці займають найбільше місця в базі даних SQL Server 2005?


90

Як ви можете визначити, які таблиці займають найбільше місця в базі даних SQL Server 2005?

Я впевнений, що існує якась збережена у системі процедура, яка відображає цю інформацію.

У мене є база даних TEST, яка зросла з 1 тб до 23 тб. В даний час ми проводимо багато тестувань перетворень клієнтів у базі даних, що передбачає запуск однієї і тієї ж збереженої процедури перетворення кілька разів. Він робить ВИДАЛЕННЯ, що, я впевнений, збільшує Журнал транзакцій. Але це змусило мене задуматися поставити це питання.

інформація

великою проблемою є таблиця dbo.Download, вона створює масивне сховище, яке насправді не потрібно, у мене було 3 ГБ до його скорочення, потім 52 МБ;)


2
Відповіді Marc_S та Barry були просто видатними, тому я підтримав їх обох і чекав, хто з них отримав найбільше голосів, щоб я міг нагородити його "Прийнятою відповіддю". Але вони обидва були пов’язані в 5, тому я просто вибрав одного, але використовував обидва. Дякуємо Marc_S та Barry!
Герхард Вайс

Відповіді:


207

Спробуйте цей сценарій - у ньому буде вказано кількість рядків та простір, який використовуються рядками даних (і загальний використовуваний простір) для всіх таблиць у вашій базі даних:

SELECT 
 t.NAME AS TableName,
 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.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
WHERE 
 t.NAME NOT LIKE 'dt%' AND
 i.OBJECT_ID > 255 AND  
 i.index_id <= 1
GROUP BY 
 t.NAME, i.object_id, i.index_id, i.name 
ORDER BY 
 OBJECT_NAME(i.object_id) 

6
+1 Блискуче. Зверніть увагу, що сюди не входить розмір індексів даних. Однак для мене це було зроблено.
Ерік Робертсон,

39
Я цього не знав, але якщо ви використовуєте Management Studio, ви також можете клацнути правою кнопкою миші на базі даних і перейти до звітів -> Використання диска за таблицею для тих самих результатів.
rossisdead

@rossisdead, це весела інформація, яку потрібно знати. Дякую!
Нікмаович

Я отримую "Таблицю" sys.tables "не існує"
Сеано,

@Seano: яку версію SQL Server ви використовуєте? (запустіть, SELECT @@VERSIONщоб з’ясувати) Який рівень сумісності бази даних має ваша база даних ??
marc_s

33

Використовуйте sp_spacedUsed

Exec sp_spaceused N'YourTableName'

Або якщо ви хочете виконати sp_spaceusedдля кожної таблиці у вашій базі даних, тоді ви можете використовувати цей SQL:

set nocount on
create table #spaceused (
  name nvarchar(120),
  rows char(11),
  reserved varchar(18),
  data varchar(18),
  index_size varchar(18),
  unused varchar(18)
)

declare Tables cursor for
  select name
  from sysobjects where type='U'
  order by name asc

OPEN Tables
DECLARE @table varchar(128)

FETCH NEXT FROM Tables INTO @table

WHILE @@FETCH_STATUS = 0
BEGIN
  insert into #spaceused exec sp_spaceused @table
  FETCH NEXT FROM Tables INTO @table
END

CLOSE Tables
DEALLOCATE Tables 

select * from #spaceused
drop table #spaceused

exec sp_spaceused

Наведений вище SQL тут


7
Для нових версій SQL Server ви також можете використовуватиexec sp_msforeachtable 'exec sp_spaceused N''?'''
JNK

1
@JNK sp_msforeachtableіснує принаймні з SQl Server 2000
SQLMenace

@SQLMenace - дякую за інформацію. Я не досліджував, скільки років йому було до публікації, але не був впевнений, що знайду його, оскільки він не оформлений документально.
JNK

4
Трохи більше простий приклад: Ви можете піти з пропускаючи EXECS і фантазії квотування, роблячи тільки , sp_msforeachtable 'sp_spaceused [?]'якщо вам подобається. Перевірено назад до SQL2000.
Марк

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

7

Коментар Россідді відповів на це запитання найкраще для мене, хотілося б, щоб це не було поховано в коментарі. Це буде корисно для таких людей, як я, які не намагаються створити сценарій рішення (OP не вимагає фрагмента коду)

Якщо ви використовуєте Management Studio, ви також можете клацнути правою кнопкою миші на базі даних і перейти до звітів -> Використання диска за таблицею для отримання тих самих результатів


Для акценту: клацніть правою кнопкою миші Базу даних, а не Екземпляр сервера
dhollenbeck,

4

Дякую @marc_s за відповідь. Мені потрібно було знати дані проти простору індексу, тому я продовжив і розширив запит, щоб включити це.

SELECT TableName
    , SUM(DataRowCounts) AS DataRowCounts
    , SUM(DataTotalSpaceGB) AS DataTotalSpaceGB
    , SUM(DataSpaceUsedGB) AS DataSpaceUsedGB
    , SUM(DataUnusedSpaceGB) AS DataUnusedSpaceGB
    , SUM(IndexRowCounts) AS IndexRowCounts
    , SUM(IndexTotalSpaceGB) AS IndexTotalSpaceGB
    , SUM(IndexSpaceUsedGB) AS IndexSpaceUsedGB
    , SUM(IndexUnusedSpaceGB) AS IndexUnusedSpaceGB
    , SUM(DataTotalSpaceGB) + SUM(IndexTotalSpaceGB) AS TotalSpaceGB
FROM
(
SELECT t.NAME AS TableName
    , i.type_desc AS IndexType
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS DataTotalSpaceGB
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2))  ELSE 0 END AS DataSpaceUsedGB    
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS DataUnusedSpaceGB
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN SUM(p.Rows) ELSE 0 END AS DataRowCounts
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS IndexTotalSpaceGB
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2))  ELSE 0 END AS IndexSpaceUsedGB    
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS IndexUnusedSpaceGB  
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN SUM(p.Rows) ELSE 0 END AS IndexRowCounts
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 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
    AND s.Name = 'dbo' --update this filter
    AND t.Name = 'MyTable'
GROUP BY t.Name
    , i.type_desc
) x
GROUP BY TableName
ORDER BY TotalSpaceGB DESC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.