Sql как найти самую большую таблицу

Обновлено 15.12.2014

Как найти самые большие таблицы в базе данных MS SQL

Как найти самые большие таблицы в базе данных 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

  1. Откройте Microsoft SQL Server Management Studio, и зарегистрируйтесь
  2. Нажмите на кнопку New Query
  3. Скопируйте нижеследующий скрипт в окно 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

USE [DatabaseName]

GO

CREATE TABLE #temp (

table_name sysname ,

row_count INT,

reserved_size VARCHAR(50),

data_size VARCHAR(50),

index_size VARCHAR(50),

unused_size VARCHAR(50))

SET NOCOUNT ON

INSERT #temp

EXEC sp_msforeachtable 'sp_spaceused ''?'''

SELECT a.table_name,

a.row_count,

COUNT(*) AS col_count,

a.data_size

FROM #temp a

INNER JOIN information_schema.columns b

ON a.table_name collate database_default

= b.table_name collate database_default

GROUP BY a.table_name, a.row_count, a.data_size

ORDER BY CAST(REPLACE(a.data_size, ' KB', '') AS integer) DESC

DROP TABLE #temp

нажмите на кнопку 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's user avatar

APC

143k19 gold badges168 silver badges281 bronze badges

asked Mar 16, 2017 at 9:43

user3661564's user avatar

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

Wernfried Domscheit's user avatar

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 Limbu's user avatar

Ram LimbuRam Limbu

4222 gold badges8 silver badges15 bronze badges

2

Добавить комментарий