데이터베이스의 모든 테이블 크기 가져 오기


1271

상당히 큰 SQL Server 데이터베이스를 상속했습니다. 포함 된 데이터를 감안할 때 예상보다 많은 공간을 차지하는 것 같습니다.

각 테이블이 소비하는 디스크 공간을 쉽게 결정할 수있는 방법이 있습니까?


어떤 역할에 액세스 할 수 있습니까? DBA입니까, 아니면 웹 호스트, 클라이언트 또는 이와 유사한 것을 통해 관리됩니까?
Rob Allen


@RobAllen 데이터베이스에 대한 모든 액세스 권한이 있으므로 역할이 필요한 스크립트이면 충분합니다.
Eric


Azure의 경우 이것을 사용 했습니다
Irf

답변:


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
스크립트에 필터링 된 인덱스에 문제가 있습니다. 주어진 테이블에 대해 필터링 된 각 인덱스에 대해 결과에 해당 테이블 이름을 가진 추가 행이 표시됩니다. 이러한 각 추가 행의 "RowCounts"는 필터링 된 인덱스 중 하나에 포함 된 행 수에 해당합니다. (Sql2012에서)
Akos Lukacs

37
@Todd : 어떤 사람들은 그런 식으로 주문하기를 원한다-다른 사람들은 테이블 이름으로 그것을 원한다-당신의 선택을 취하고 필요에 따라 코드를 적응 시키십시오. ...
marc_s

12
테이블이 분할 된 경우 진행중인 작업에 대한 표시없이 여러 번 표시됩니다. p.partition_number를 선택 목록에 추가하거나 SUM (p.Rows)하여 그룹에서 제거 할 수 있습니다.
PRMan

561

당신이 사용하는 경우 SQL Server 관리 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을 실행할 수 있습니다. :) 참고 (BTW, 난 여전히 당신의 대답을 upvoted)
앤드류 Steitz

8
Azure SQL에 존재하지 않는 것 같습니다 :-(
Simon_Weaver

1
나는 그것이 심각하지 않다는 것을 알고 있지만, 당신은 엔지니어링 및 기술에서 소외 계층을 밀어내어 어디에서나이 추론을 반복합니다. 두 가지를 모두 배워야하지만 시간 절약 유틸리티를 사용하여 더 똑똑하고 빠르게 작업하는 사람들을 징계해서는 안됩니다. (SSMS가 때때로 "느려진 유틸리티"인 것 같지만 ... : X) 개인적으로 테이블 형식 데이터의 판독 값은 일반적으로 GUI에서 더 명확하지만, Microsoft에서 만든 도구는 모든 UI 관련 예외입니다.
Julia McGuigan

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 에서 사용 System.OutOfMemoryException하면 테이블 수가 많은 경우 쉽게 트리거 될 수 있으므로 임시 테이블을 사용하여 결과를 저장하는 것이 좋습니다.
syneticon-dj 2016

1
sp_spacedused에서 볼 수있는 주요 문제는 인간이 읽을 수있는 형식으로 데이터를 반환하는 것으로 보입니다 (예 : 내 경우에는 '예약 된'열에 '152KB'가 있음). 적절하게 MB / GB로 전환한다고 가정합니다. 이것은 많은 상황에서 분명히 유용하지만 크기를 기반으로 논리를 적용해야하거나 값 등을 비교하려는 경우에는 유용하지 않습니다. 나는 그것을 끄는 방법을 찾았지만 찾을 수 없었습니다 (SQL Server 2005를 사용하고 있습니다 :()
DarthPablo

55

여기에 또 다른 방법 : 사용하여 SQL Server Management Studio를 에서 개체 탐색기 , 데이터베이스를 선택로 이동 테이블

여기에 이미지 설명을 입력하십시오

열기 개체 탐색기 정보를 (눌러 중 하나 F7을 하거나가는 보기 -> 개체 탐색기 정보 ). 개체 탐색기 세부 정보 페이지에서 열 머리글을 마우스 오른쪽 단추로 클릭하고 페이지에서 보려는 열을 활성화하십시오. 열별로 데이터를 정렬 할 수도 있습니다.

여기에 이미지 설명을 입력하십시오


예. Azure의 SSMS에는 로컬 버전에 비해 일부 기능이 없습니다.
Sparrow

@batmaci Azure SQL 데이터베이스에 대한 의견을 제시 할 때 이것이 제대로 작동했는지 확실하지 않지만 최신 버전의 SSMS에서 적어도 부분적으로 작동하는 것 같습니다. 나에게 그것은 테이블 메타 데이터에 대한 쿼리가 시간 초과되는 것처럼 보이지만, 그렇게하기 전에 선택한 테이블을 포함하여 (신뢰할 수있는) 몇 가지 (3-10) 테이블을 반환하는 것으로 보입니다. 테이블을 선택하고 새로 고침을 클릭하면 원하는 테이블이 표시되지 않습니다.
pcdev 2016 년

Azure는 "실제"SQL Server가 아닙니다 (ha ha)
리버스 엔지니어

나는 (+ 1) 덕분에 Azure에 이것을 사용했다
Irf

또한 NirSoft SysExporter 같은 유틸리티를 사용하여 CSV 파일의 목록을 내보낼 수 있습니다 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를 사용하여 위의 내용을 보았고 SP가 이와 같은 것을 쓰려고했는데 시간이 절약되는 것을 확인하기 위해 아래로 스크롤했습니다.
브래드

37
 exec  sp_spaceused N'dbo.MyTable'

모든 테이블에 대해 .. (Paul의 의견에서 추가)을 사용하십시오.

exec sp_MSForEachTable 'exec sp_spaceused [?]'

5
음흉 - 당신은 변경 exec sp_helpdb되는 하지 않습니다 에, 테이블에 대해 아무것도 보여 exec sp_spaceused하지만 한 번에 하나 개의 테이블 ... 그것은 당신에게 당신이 가지고있는 테이블의 개요를 제공하지 않습니다 얼마나 많은 행들이이 방법 - 어떤 않습니다 그들이 차지하는 많은 공간.
marc_s

4
exec sp_MSForEachTable 'exec sp_spaceused [?]'
Paul

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 (KB) 열을 합산하면 sp_spaceused의 index_size와 일치하지 않는 이유는 무엇입니까?
Derek

@Derek 님을 추가하여 답변을 수정했습니다 where [i].[is_primary_key] = 0. 이제 크기가 일치해야합니다.
CodeAngry 2012 년

고맙지 만 실제로 작동하지 않습니다. 나는 (매우 작은) 테스트 데이터베이스를 가지고 있는데 관심있는 테이블에는 두 개의 인덱스가 있습니다. 한 열의 기본 클러스터형 인덱스와 다른 열 중 두 개의 클러스터되지 않은 인덱스입니다. 이 쿼리는 각각 16kB를 사용하고 있지만 sp_spaceused는 총 인덱스 사용량이 24kB라고 말합니다. 혼동의 일부는 다음과 같습니다.이 쿼리를 허용 된 답변의 "UsedSpaceKB"와 비교하면 실제로 차이가 보이지 않습니다. 동일한 조인으로 sys.tables 추가가 누락되었습니다. 누락 된 것이 있습니까, 아니면이 쿼리가 본질적으로 손상 되었습니까?
Derek

큰 데이터베이스가 있습니다. 그리고 크기는와 일치합니다 sp_spaceused. GB를 측정하므로 일치하지 않는 몇 메가는 그리 많지 않습니다. 나는 정확한 크기에 신경 쓰지 않고 단지 아이디어입니다.
CodeAngry

14

SSMS의 '테이블 속성-스토리지'페이지에있는 것과 정확히 같은 숫자를 계산해야하는 경우 SSMS에서와 동일한 방법으로 계산해야합니다 (sql server 2005 이상에서 작동 함 ... "used_pages"만 계산하면 정확한 색인 크기를 표시하기에 충분하지 않기 때문에 LOB 필드가있는 테이블에 대해 올바르게 작동합니다.

;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 확장 은 MB 및 GB 크기의 테이블 파티션을 처리하는 응답 입니다. SQL 서버 2,012분의 2,008에서 테스트 (여기서 라인을 댓글 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

이것이 최고의 답변이되어야합니다.
Baodad

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가 수행하는 방식과 일치하고 파티션을 올바르게 처리하는 스크립트에 감사드립니다.
Mike

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. 마지막으로 위의 도구 모음 에서 표시된 실행 버튼을 빨간색 으로 누르십시오 .

  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에만 해당되며 내 환경에서 작동하도록 테스트되었습니다.

이 코드는 단일 데이터베이스뿐만 아니라 단일 인스턴스의 가능한 모든 데이터베이스에 액세스 합니다.

두 개의 임시 테이블을 사용하여 적절한 데이터를 수집 한 다음 결과를 하나의 '라이브'테이블로 덤프합니다.

반환 된 데이터는 DatabaseName, DatabaseTableName, Rows (테이블), data (테이블의 크기는 KB로 표시됨), 항목 데이터입니다 (스크립트를 마지막으로 실행 한 시점을 알 때 유용합니다).

이 코드의 몰락은 'data'필드가 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

다음은 크기가 내림차순으로 정렬 된 1GB보다 큰 테이블을 가져 오는 샘플 쿼리입니다.

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