Обновлено 15.12.2014
Как найти самые большие таблицы в базе данных MS SQL
Если ваша база данных на практике оказывается больше, чем вы ожидали, то очень полезно будет узнать, какие именно таблицы выросли и увеличили общий объем базы данных.
Эта статья покажет вам, как можно просмотреть список больших по размеру таблиц баз данных MS SQL. Таблицы будут выведены по мене уменьшения их размера, то есть самые большие таблицы окажутся вверху списка.
Все что потребуется, это установка Microsoft SQL Server Management Studio на вашем компьютере. Если эта оснастка уже установлена, тем лучше.
Менеджер Microsoft SQL Server Management Studio Express 2008 доступен для свободного скачивания на сайте Microsoft, вы можете перейти к нему по ссылке: www.microsoft.com/download/en/details.aspx?id=22985
- Откройте Microsoft SQL Server Management Studio, и зарегистрируйтесь
- Нажмите на кнопку New Query
- Скопируйте нижеследующий скрипт в окно New Query, не забывая заменять [DatabaseName] на имя вашей реальной базы
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
нажмите на кнопку Execute
Дек 15, 2014 21:48
@marc_s’s answer is very great and I’ve been using it for few years. However, I noticed that the script misses data in some columnstore indexes and doesn’t show complete picture. E.g. when you do SUM(TotalSpace)
against the script and compare it with total space database property in Management Studio the numbers don’t match in my case (Management Studio shows larger numbers). I modified the script to overcome this issue and extended it a little bit:
select
tables.[name] as table_name,
schemas.[name] as schema_name,
isnull(db_name(dm_db_index_usage_stats.database_id), 'Unknown') as database_name,
sum(allocation_units.total_pages) * 8 as total_space_kb,
cast(round(((sum(allocation_units.total_pages) * 8) / 1024.00), 2) as numeric(36, 2)) as total_space_mb,
sum(allocation_units.used_pages) * 8 as used_space_kb,
cast(round(((sum(allocation_units.used_pages) * 8) / 1024.00), 2) as numeric(36, 2)) as used_space_mb,
(sum(allocation_units.total_pages) - sum(allocation_units.used_pages)) * 8 as unused_space_kb,
cast(round(((sum(allocation_units.total_pages) - sum(allocation_units.used_pages)) * 8) / 1024.00, 2) as numeric(36, 2)) as unused_space_mb,
count(distinct indexes.index_id) as indexes_count,
max(dm_db_partition_stats.row_count) as row_count,
iif(max(isnull(user_seeks, 0)) = 0 and max(isnull(user_scans, 0)) = 0 and max(isnull(user_lookups, 0)) = 0, 1, 0) as no_reads,
iif(max(isnull(user_updates, 0)) = 0, 1, 0) as no_writes,
max(isnull(user_seeks, 0)) as user_seeks,
max(isnull(user_scans, 0)) as user_scans,
max(isnull(user_lookups, 0)) as user_lookups,
max(isnull(user_updates, 0)) as user_updates,
max(last_user_seek) as last_user_seek,
max(last_user_scan) as last_user_scan,
max(last_user_lookup) as last_user_lookup,
max(last_user_update) as last_user_update,
max(tables.create_date) as create_date,
max(tables.modify_date) as modify_date
from
sys.tables
left join sys.schemas on schemas.schema_id = tables.schema_id
left join sys.indexes on tables.object_id = indexes.object_id
left join sys.partitions on indexes.object_id = partitions.object_id and indexes.index_id = partitions.index_id
left join sys.allocation_units on partitions.partition_id = allocation_units.container_id
left join sys.dm_db_index_usage_stats on tables.object_id = dm_db_index_usage_stats.object_id and indexes.index_id = dm_db_index_usage_stats.index_id
left join sys.dm_db_partition_stats on tables.object_id = dm_db_partition_stats.object_id and indexes.index_id = dm_db_partition_stats.index_id
group by schemas.[name], tables.[name], isnull(db_name(dm_db_index_usage_stats.database_id), 'Unknown')
order by 5 desc
Hope it will be helpful for someone.
This script was tested against large TB-wide databases with hundreds of different tables, indexes and schemas.
Query below list ten largest tables in database.
Query
select top 10 schema_name(tab.schema_id) + '.' + tab.name as [table],
cast(sum(spc.used_pages * 8)/1024.00 as numeric(36, 2)) as used_mb,
cast(sum(spc.total_pages * 8)/1024.00 as numeric(36, 2)) as allocated_mb
from sys.tables tab
join sys.indexes ind
on tab.object_id = ind.object_id
join sys.partitions part
on ind.object_id = part.object_id and ind.index_id = part.index_id
join sys.allocation_units spc
on part.partition_id = spc.container_id
group by schema_name(tab.schema_id) + '.' + tab.name
order by sum(spc.used_pages) desc;
Columns
- table – table name with schema name
- used_mb – size of space actually in use by table in MB
- allocated_mb – size of allocated or reserved space by this table in MB
Rows
- One row represents one table
- Scope of rows: ten tables which uses most space
- Ordered by actually used space
Sample results
From time to time, I need to find the largest tables in terms of rows / used space / total space etc. I originally used sp_spaceused, a temp table and a cursor (or sp_MSForEachTable) and put them into a stored procedure to get the information I need.
But now as I am working more on table partition management, I find there is a DMV that can give me the exactly info I need, and what surprises me is that sp_spaceused is actually using this DMV, i.e. sys.dm_db_partition_stats to get the data as well. So here is the one sql to get the largest tables in a db (only applicable to sql server 2k5 / 2k8 for tables without xml indexes)
— find the table size info (no xml index) using sys.dm_db_partition_stats
— Author: Jeffrey Yao
— Date: Sept 27, 2010
select name=object_schema_name(object_id) + ‘.’ + object_name(object_id)
, rows=sum(case when index_id < 2 then row_count else 0 end)
, reserved_kb=8*sum(reserved_page_count)
, data_kb=8*sum( case
when 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 )
, index_kb=8*(sum(used_page_count)
– sum( case
when 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 )
)
, unused_kb=8*sum(reserved_page_count-used_page_count)
from sys.dm_db_partition_stats
where object_id > 1024
group by object_id
order by
rows desc
— data_kb desc
— reserved_kb desc
— data_kb desc
— index_kb desc
— unsed_kb desc
I create following SQL statement but it show me biggest tables in general. I want to see it for each tablespace.
select tablespace_name, max(BYTES/1024/1024), SEGMENT_NAME
from dba_segments
where SEGMENT_TYPE='TABLE'
group by tablespace_name,SEGMENT_NAME,tablespace_name
Any ideas?
APC
143k19 gold badges168 silver badges281 bronze badges
asked Mar 16, 2017 at 9:43
3
You can make it shorter when you use FIRST function:
SELECT tablespace_name, MAX(BYTES/1024/1024),
MAX(SEGMENT_NAME) KEEP (DENSE_RANK LAST ORDER BY BYTES)
FROM dba_segments
WHERE SEGMENT_TYPE = 'TABLE'
GROUP BY tablespace_name;
Note, due to SEGMENT_TYPE = 'TABLE'
your query will not include partitionized tables.
Another note, you will get only one table per tablespace in case several tables have exactly the same size. Use solution from APC in cause you need all tables.
answered Mar 16, 2017 at 10:04
6
Use Analytical function to rank table in order of size:
SELECT
tablespace_name,segment_name,tab_size_mb
FROM
(
SELECT
tablespace_name,segment_name,bytes/1024/1024 tab_size_mb,
RANK() OVER (PARTITION BY tablespace_name ORDER BY bytes DESC) AS rnk
FROM dba_segments
WHERE segment_type='TABLE'
)
WHERE rnk=1;
answered Mar 16, 2017 at 10:28
Ram LimbuRam Limbu
4222 gold badges8 silver badges15 bronze badges
2