SQL Server 데이터베이스에서 가장 큰 개체를 찾는 방법은 무엇입니까?


136

SQL Server 데이터베이스에서 가장 큰 개체를 찾으려면 어떻게해야합니까? 먼저, 어떤 테이블 (및 관련 인덱스)이 가장 큰지 확인한 다음 특정 테이블의 어떤 행이 가장 큰지 결정합니다 (이진 데이터를 BLOB에 저장)?

이런 종류의 데이터베이스 분석에 도움이되는 도구가 있습니까? 아니면 시스템 테이블에 대해 실행할 수있는 간단한 쿼리가 있습니까?

답변:


280

나는이 SQL 스크립트 (어딘가에서 얻은 것-어디에서 왔는지 재구성 할 수 없음)를 오랫동안 사용해 왔으며 인덱스와 테이블의 크기를 이해하고 결정하는 데 도움이되었습니다.

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) 

물론 다른 주문 기준을 사용할 수도 있습니다.

ORDER BY SUM(p.rows) DESC

행이 가장 많은 테이블을 가져 오거나

ORDER BY SUM(a.total_pages) DESC

가장 많은 페이지 (8K 블록)가 사용 된 테이블을 가져옵니다.


훌륭 해요, 고맙습니다! 이제 가장 큰 객체를 많은 이진 데이터를 포함하는 테이블로 좁혔습니다. 어쨌든 이진 데이터 행 중 가장 큰 행을 알아 내기 위해?
jamesaharvey 2016 년

3
이를 위해서는 해당 테이블을 선택하고 관심있는 각 필드 (일반적으로 VARCHAR (MAX), VARBINARY (MAX) 등)에 대해 DATALENGTH (필드)를 인쇄해야합니다.
marc_s

1
@marc_s에게 감사드립니다. 이것은 매우 유용했습니다. TableName 열에는 다음과 같은 스키마 이름도 포함될 수 있습니다.SELECT OBJECT_SCHEMA_NAME(i.object_id) + '.' + OBJECT_NAME(i.object_id) AS TableName, ...
CruiZen

2
그것은 내가 본 것 중 가장 아름다운 TSQL 스크립트 여야합니다
Agustin Meriles

2
비 클러스터형 인덱스도 포함 시키려면 WHERE 절에서 "and i.index_id <= 1"을 제거하십시오.
Gordon Bell

72

SQL Server 2008에서는 최상위 테이블 별 표준 디스크 사용 보고서를 실행할 수도 있습니다. DB 를 마우스 오른쪽 단추로 클릭 하고 보고서-> 표준 보고서를 선택한 후 원하는 보고서를 선택 하면 찾을 수 있습니다 .


8
농담 없어요? 그것은 그러한 혁신적인 대답입니다. 게시 해 주셔서 감사합니다. (sarcasm이 아닙니다. 한동안이 쿼리를 수동으로 실행했지만이 보고서가 이미 있다고 믿을 수 없습니다!)
Jennifer Zouak

4

이 쿼리는 연결에서 가장 큰 테이블을 찾는 데 도움이됩니다.

SELECT  TOP 1 OBJECT_NAME(OBJECT_ID) TableName, st.row_count
FROM sys.dm_db_partition_stats st
WHERE index_id < 2
ORDER BY st.row_count DESC

우리가 쉽게 암기 할 수있는 것을 갖는 것이 좋습니다. 간결한 주셔서 감사합니다.
David Betz

3

다음 코드를 사용할 수도 있습니다.

USE AdventureWork
GO
CREATE TABLE #GetLargest 
(
  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 #GetLargest

EXEC sp_msforeachtable 'sp_spaceused ''?'''

SELECT 
  a.table_name,
  a.row_count,
  COUNT(*) AS col_count,
  a.data_size
  FROM #GetLargest 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 #GetLargest

2

Sql Server Management Studio 2008을 사용하는 경우 개체 탐색기 세부 정보 창에서 볼 수있는 특정 데이터 필드가 있습니다. 테이블 폴더를 찾아서 선택하십시오. 세부 사항보기에서 열 제목을 마우스 오른쪽 단추로 클릭하고 "보고서"에 필드를 추가 할 수 있습니다. SSMS 2008 Express를 이용하는 경우 마일리지가 다를 수 있습니다.


2

이 쿼리는 SqlServerCentral에서도 매우 유용합니다. 여기에 원래 게시물에 대한 링크가 있습니다.

SQL Server 최대 테이블

  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   

내 데이터베이스에서 그들은이 쿼리와 첫 번째 답변 사이에 다른 결과를주었습니다.

누군가가 유용하다고 생각하기를 바랍니다.


1

@marc_s의 답변은 매우 훌륭하며 몇 년 동안 사용해 왔습니다. 그러나 스크립트가 일부 columnstore 인덱스의 데이터를 누락하고 완전한 그림을 표시하지 않는 것으로 나타났습니다. 예를 들어 SUM(TotalSpace)스크립트에 대해 수행 하고 Management Studio의 총 공간 데이터베이스 속성과 비교하면 숫자가 일치하지 않습니다 (Management Studio가 더 큰 숫자를 표시 함). 이 문제를 극복하기 위해 스크립트를 수정하고 조금 확장했습니다.

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

누군가에게 도움이되기를 바랍니다. 이 스크립트는 수백 개의 서로 다른 테이블, 인덱스 및 스키마가있는 대형 TB 전체 데이터베이스에 대해 테스트되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.