사용하지 않는 공간을 회수하려고하면 SQL Server에서 사용 된 공간이 크게 증가합니다.


15

프로덕션 데이터베이스에 525GB 크기의 테이블이 있는데 그 중 383GB는 사용되지 않습니다.

사용하지 않은 공간

이 공간 중 일부를 되찾고 싶지만 프로덕션 DB를 망치기 전에 데이터가 적은 테스트 DB의 동일한 테이블에서 일부 전략을 테스트하고 있습니다. 이 테이블에는 비슷한 문제가 있습니다.

사용하지 않은 공간

테이블에 대한 일부 정보 :

  • 채우기 비율이 0으로 설정되었습니다.
  • 약 30 개의 열이 있습니다
  • 열 중 하나는 이미지 유형의 LOB이며 크기는 몇 KB에서 수백 MB 사이 인 파일을 저장합니다.
  • 테이블에 관련된 가상 인덱스가 없습니다

서버에서 SQL Server 2017 (RTM-GDR) (KB4505224)-14.0.2027.2 (X64)를 실행 중입니다. 데이터베이스가 SIMPLE복구 모델을 사용 중 입니다.

내가 시도한 것들 :

  • 인덱스 재 구축 : ALTER INDEX ALL ON dbo.MyTable REBUILD. 이것은 무시할만한 영향을 미쳤다.
  • 인덱스 재구성 : ALTER INDEX ALL ON dbo.MyTable REORGANIZE WITH(LOB_COMPACTION = ON). 이것은 무시할만한 영향을 미쳤다.
  • LOB 열을 다른 테이블에 복사하고 열을 삭제하고 열을 다시 만든 다음 데이터를 다시 복사했습니다 (이 게시물에 설명 된대로 사용되지 않은 공간 SQL Server 테이블 해제 ). 이것은 사용되지 않은 공간을 줄 였지만 사용 된 공간으로 변환하는 것처럼 보였습니다.

    사용하지 않은 공간

  • bcp 유틸리티를 사용하여 테이블을 내보내고 자르고 다시로드합니다 (이 글에서 설명 된대로 테이블에 사용되지 않은 공간을 확보하는 방법 ). 이것은 또한 사용되지 않은 공간을 줄이고 위의 이미지와 비슷한 정도로 사용 된 공간을 늘 렸습니다.

  • 권장되지는 않지만 DBCC SHRINKFILE 및 DBCC SHRINKDATABASE 명령을 시도했지만 사용되지 않은 공간에는 영향을 미치지 않았습니다.
  • 달리기 DBCC CLEANTABLE('myDB', 'dbo.myTable')는 차이가 없었습니다
  • 이미지 및 텍스트 데이터 유형을 유지하면서 데이터 유형을 varbinary (max) 및 varchar (max)로 변경 한 후 위의 모든 것을 시도했습니다.
  • 데이터를 새로운 데이터베이스의 새 테이블로 가져 오려고 시도했지만 사용되지 않은 공간 만 사용 된 공간으로 변환했습니다. 나는 이 게시물 에서이 시도의 세부 사항을 설명했다 .

이것이 내가 기대할 수있는 결과라면 프로덕션 DB에서 이러한 시도를하고 싶지 않습니다.

  1. 이러한 시도 후에 사용되지 않은 공간이 사용 된 공간으로 변환되는 이유는 무엇입니까? 나는 후드에서 무슨 일이 일어나고 있는지 잘 이해하지 못하는 것 같습니다.
  2. 사용 된 공간을 늘리지 않고 사용되지 않은 공간을 줄이기 위해 다른 방법이 있습니까?

편집 : 다음은 테이블에 대한 디스크 사용량 보고서 및 스크립트입니다.

디스크 사용량

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MyTable](
    [Column1]  [int] NOT NULL,
    [Column2]  [int] NOT NULL,
    [Column3]  [int] NOT NULL,
    [Column4]  [bit] NOT NULL,
    [Column5]  [tinyint] NOT NULL,
    [Column6]  [datetime] NULL,
    [Column7]  [int] NOT NULL,
    [Column8]  [varchar](100) NULL,
    [Column9]  [varchar](256) NULL,
    [Column10] [int] NULL,
    [Column11] [image] NULL,
    [Column12] [text] NULL,
    [Column13] [varchar](100) NULL,
    [Column14] [varchar](6) NULL,
    [Column15] [int] NOT NULL,
    [Column16] [bit] NOT NULL,
    [Column17] [datetime] NULL,
    [Column18] [varchar](50) NULL,
    [Column19] [varchar](50) NULL,
    [Column20] [varchar](60) NULL,
    [Column21] [varchar](20) NULL,
    [Column22] [varchar](120) NULL,
    [Column23] [varchar](4) NULL,
    [Column24] [varchar](75) NULL,
    [Column25] [char](1) NULL,
    [Column26] [varchar](50) NULL,
    [Column27] [varchar](128) NULL,
    [Column28] [varchar](50) NULL,
    [Column29] [int] NULL,
    [Column30] [text] NULL,
 CONSTRAINT [PK] PRIMARY KEY CLUSTERED 
(
    [Column1] ASC,
    [Column2] ASC,
    [Column3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column4]  DEFAULT (0) FOR [Column4]
GO
ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column5]  DEFAULT (0) FOR [Column5]
GO
ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column15]  DEFAULT (0) FOR [Column15]
GO
ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column16]  DEFAULT (0) FOR [Column16]
GO

Max Vernon의 답변에서 명령을 실행 한 결과는 다음과 같습니다.

╔════════════╦═══════════╦════════════╦═════════════════╦══════════════════════╦════════════════════╗
 TotalBytes  FreeBytes  TotalPages  TotalEmptyPages  PageBytesFreePercent  UnusedPagesPercent 
╠════════════╬═══════════╬════════════╬═════════════════╬══════════════════════╬════════════════════╣
  9014280192 8653594624     1100376          997178             95.998700           90.621500 
╚════════════╩═══════════╩════════════╩═════════════════╩══════════════════════╩════════════════════╝
╔═════════════╦═══════════════════╦════════════════════╗
 ObjectName   ReservedPageCount       UsedPageCount 
╠═════════════╬═══════════════════╬════════════════════╣
 dbo.MyTable            5109090             2850245 
╚═════════════╩═══════════════════╩════════════════════╝

최신 정보:

Max Vernon이 제안한대로 다음을 실행했습니다.

DBCC UPDATEUSAGE (N'<database_name>', N'<table_name>');

그리고 출력은 다음과 같습니다.

DBCC UPDATEUSAGE: Usage counts updated for table 'MyTable' (index 'PK_MyTable', partition 1):
        USED pages (LOB Data): changed from (568025) to (1019641) pages.
        RSVD pages (LOB Data): changed from (1019761) to (1019763) pages.

테이블의 디스크 사용량이 업데이트되었습니다.

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

그리고 전체 디스크 사용량 :

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

따라서 SQL Server에서 추적 한 디스크 사용량이 실제 디스크 사용량과 크게 일치하지 않는 것이 문제인 것 같습니다. 이 문제가 해결 된 것으로 간주하지만, 왜 이런 일이 처음에 발생했는지 알고 싶습니다.

답변:


10

증상이 일치하지 않는 공간 사용을 나타 내기 때문에 첫 번째 단계로 테이블에 대해 DBCC UPDATEUSAGE 를 실행했습니다 .

DBCC UPDATEUSAGE는 테이블 또는 인덱스의 각 파티션에 대한 행, 사용 된 페이지, 예약 된 페이지, 리프 페이지 및 데이터 페이지 수를 수정합니다. 시스템 테이블에 부정확성이 없으면 DBCC UPDATEUSAGE는 데이터를 리턴하지 않습니다. 부정확성이 발견되어 정정되고 WITH NO_INFOMSGS가 사용되지 않으면 DBCC UPDATEUSAGE는 시스템 테이블에서 갱신중인 행과 열을 리턴합니다.

구문은 다음과 같습니다.

DBCC UPDATEUSAGE (N'<database_name>', N'<table_name>');

당신이 그것을 실행 한 후, 나는 EXEC sys.sp_spaceused테이블에 대해 실행할 것입니다 .

EXEC sys.sp_spaceused @objname = N'dbo.MyTable'
    , @updateusage = 'false' --true or false
    , @mode = 'ALL' --ALL, LOCAL_ONLY, REMOTE_ONLY
    , @oneresultset = 1;

위 명령에는 사용법을 업데이트하는 옵션이 있지만 DBCC UPDATEUSAGE먼저 수동으로 실행했기 때문에 해당 설정을 false로 두십시오. DBCC UPDATEUSAGE수동으로 실행 하면 문제가 해결되었는지 확인할 수 있습니다.

다음 쿼리는 테이블에서 사용 가능한 바이트 백분율과 테이블에서 사용 가능한 페이지 백분율을 표시해야합니다. 쿼리는 문서화되지 않은 기능을 사용하기 때문에 결과에 의존하는 것은 현명하지 않지만 sys.sp_spaceused높은 수준에서 의 출력과 비교하면 정확 해 보입니다 .

사용 가능한 바이트의 백분율이 사용 가능한 페이지의 백분율보다 상당히 높으면 부분적으로 비어있는 페이지가 많이 있습니다.

부분적으로 빈 페이지는 다음과 같은 여러 가지 원인으로 인해 발생할 수 있습니다.

  1. 페이지 분할 (클러스터형 인덱스에 새 삽입을 수용하기 위해 페이지를 분할해야 함)

  2. 열 크기로 인해 페이지를 열로 채울 수 없습니다.

쿼리는 문서화되지 않은 sys.dm_db_database_page_allocations동적 관리 기능을 사용합니다 .

;WITH dpa AS 
(
    SELECT dpa.*
        , page_free_space_percent_corrected = 
          CASE COALESCE(dpa.page_type_desc, N'')
            WHEN N'TEXT_MIX_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
            WHEN N'TEXT_TREE_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
            ELSE COALESCE(dpa.page_free_space_percent, 100)
          END
    FROM sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID('dbo.MyTable'), NULL, NULL, 'DETAILED') dpa
)
, src AS
(
SELECT TotalKB = COUNT_BIG(1) * 8192 / 1024
    , FreeKB = SUM((dpa.page_free_space_percent_corrected / 100) * CONVERT(bigint, 8192)) / 1024
    , TotalPages = COUNT_BIG(1)
    , TotalEmptyPages = SUM(CASE WHEN dpa.page_free_space_percent_corrected = 100 THEN 1 ELSE 0 END) --completely empty pages
FROM dpa
)
SELECT *
    , BytesFreePercent = (CONVERT(decimal(38,2), src.FreeKB) / src.TotalKB) * 100
    , UnusedPagesPercent = (CONVERT(decimal(38,2), src.TotalEmptyPages) / src.TotalPages) * 100
FROM src

출력은 다음과 같습니다.

╔ ========== ╦ ======== ╦ ============= ╦ ================== ╦ ==================== ╦ ======================
KB TotalKB ║ FreeKB ║ TotalPages ║ TotalEmptyPages tes BytesFreePercent ║ UnusedPagesPercent ║
╠ ========== ╬ ======== ╬ ============= ╬ ================== ╬ ==================== ╬ ======================
║ 208 ║ 96 ║ 26 ║ 12 ║ 46.153800 ║ 46.153800 ║
╚ ========== ╩ ======== ╩ ============= ╩ ================== ╩ ==================== ╩ ======================

여기 에 기능을 설명하는 블로그 게시물을 작성했습니다 .

귀하의 시나리오에서을 실행 한 이후에의 ALTER TABLE ... REBUILD숫자가 매우 낮아야 TotalEmptyPages하지만에서 약 72 %를 유지하고 있다고 생각합니다 BytesFreePercent.

CREATE TABLE스크립트를 사용 하여 시나리오를 다시 작성했습니다.

이것은 내가 사용 하는 MCVE입니다 .

DROP TABLE IF EXISTS dbo.MyTable;

CREATE TABLE [dbo].[MyTable](
    [Column1]  [int]            NOT NULL IDENTITY(1,1),
    [Column2]  [int]            NOT NULL,
    [Column3]  [int]            NOT NULL,
    [Column4]  [bit]            NOT NULL,
    [Column5]  [tinyint]        NOT NULL,
    [Column6]  [datetime]       NULL,
    [Column7]  [int]            NOT NULL,
    [Column8]  [varchar](100)   NULL,
    [Column9]  [varchar](256)   NULL,
    [Column10] [int]            NULL,
    [Column11] [image]          NULL,
    [Column12] [text]           NULL,
    [Column13] [varchar](100)   NULL,
    [Column14] [varchar](6)     NULL,
    [Column15] [int]            NOT NULL,
    [Column16] [bit]            NOT NULL,
    [Column17] [datetime]       NULL,
    [Column18] [varchar](50)    NULL,
    [Column19] [varchar](50)    NULL,
    [Column20] [varchar](60)    NULL,
    [Column21] [varchar](20)    NULL,
    [Column22] [varchar](120)   NULL,
    [Column23] [varchar](4)     NULL,
    [Column24] [varchar](75)    NULL,
    [Column25] [char](1)        NULL,
    [Column26] [varchar](50)    NULL,
    [Column27] [varchar](128)   NULL,
    [Column28] [varchar](50)    NULL,
    [Column29] [int]            NULL,
    [Column30] [text]           NULL,
 CONSTRAINT [PK] PRIMARY KEY CLUSTERED 
(
    [Column1] ASC,
    [Column2] ASC,
    [Column3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column4]  DEFAULT (0) FOR [Column4]

ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column5]  DEFAULT (0) FOR [Column5]

ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column15]  DEFAULT (0) FOR [Column15]

ALTER TABLE [dbo].[MyTable] ADD  CONSTRAINT [DF_Column16]  DEFAULT (0) FOR [Column16]
GO

INSERT INTO dbo.MyTable (
      Column2
    , Column3
    , Column4
    , Column5
    , Column6
    , Column7
    , Column8
    , Column9
    , Column10
    , Column11
    , Column12
    , Column13
    , Column14
    , Column15
    , Column16
    , Column17
    , Column18
    , Column19
    , Column20
    , Column21
    , Column22
    , Column23
    , Column24
    , Column25
    , Column26
    , Column27
    , Column28
    , Column29
    , Column30
)
VALUES (
          0
        , 0
        , 0
        , 0
        , '2019-07-09 00:00:00'
        , 1
        , REPLICATE('A', 50)    
        , REPLICATE('B', 128)   
        , 0
        , REPLICATE(CONVERT(varchar(max), 'a'), 1)
        , REPLICATE(CONVERT(varchar(max), 'b'), 9000)
        , REPLICATE('C', 50)    
        , REPLICATE('D', 3)     
        , 0
        , 0
        , '2019-07-10 00:00:00'
        , REPLICATE('E', 25)    
        , REPLICATE('F', 25)    
        , REPLICATE('G', 30)    
        , REPLICATE('H', 10)    
        , REPLICATE('I', 120)   
        , REPLICATE('J', 4)     
        , REPLICATE('K', 75)    
        , 'L'       
        , REPLICATE('M', 50)    
        , REPLICATE('N', 128)   
        , REPLICATE('O', 50)    
        , 0
        , REPLICATE(CONVERT(varchar(max), 'c'), 90000)
);
--GO 100

;WITH dpa AS 
(
    SELECT dpa.*
        , page_free_space_percent_corrected = 
          CASE COALESCE(dpa.page_type_desc, N'')
            WHEN N'TEXT_MIX_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
            WHEN N'TEXT_TREE_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
            ELSE COALESCE(dpa.page_free_space_percent, 100)
          END
    FROM sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID('dbo.MyTable'), NULL, NULL, 'DETAILED') dpa
)
, src AS
(
SELECT TotalKB = COUNT_BIG(1) * 8192 / 1024
    , FreeKB = SUM((dpa.page_free_space_percent_corrected / 100) * CONVERT(bigint, 8192)) / 1024
    , TotalPages = COUNT_BIG(1)
    , TotalEmptyPages = SUM(CASE WHEN dpa.page_free_space_percent_corrected = 100 THEN 1 ELSE 0 END) --completely empty pages
FROM dpa
)
SELECT *
    , BytesFreePercent = (CONVERT(decimal(38,2), src.FreeKB) / src.TotalKB) * 100
    , UnusedPagesPercent = (CONVERT(decimal(38,2), src.TotalEmptyPages) / src.TotalPages) * 100
FROM src

다음 쿼리는 테이블에 할당 된 각 페이지에 대해 한 줄을 표시하고 문서화되지 않은 동일한 DMV를 사용합니다.

SELECT DatabaseName = d.name
    , ObjectName = o.name
    , IndexName = i.name
    , PartitionID = dpa.partition_id
    , dpa.allocation_unit_type_desc
    , dpa.allocated_page_file_id
    , dpa.allocated_page_page_id
    , dpa.is_allocated
    , dpa.page_free_space_percent --this seems unreliable
    , page_free_space_percent_corrected = 
        CASE COALESCE(dpa.page_type_desc, N'')
        WHEN N'TEXT_MIX_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
        WHEN N'TEXT_TREE_PAGE' THEN 100 - COALESCE(dpa.page_free_space_percent, 100)
        ELSE COALESCE(dpa.page_free_space_percent, 100)
        END
    , dpa.page_type_desc
    , dpa.is_page_compressed
    , dpa.has_ghost_records
FROM sys.dm_db_database_page_allocations(DB_ID(), OBJECT_ID('dbo.MyTable'), NULL, NULL, 'DETAILED') dpa
    LEFT JOIN sys.databases d ON dpa.database_id = d.database_id
    LEFT JOIN sys.objects o ON dpa.object_id = o.object_id
    LEFT JOIN sys.indexes i ON dpa.object_id = i.object_id AND dpa.index_id = i.index_id
WHERE dpa.database_id = DB_ID() --sanity check for sys.objects and sys.indexes

테스트 환경에서 실제 테이블에 대해 실행하면 출력에 많은 행 이 표시 되지만 문제의 위치를 ​​볼 수 있습니다.

다음 스크립트를 실행하고 질문에 결과를 게시 할 수 있습니까? 우리가 같은 페이지에 있는지 확인하려고합니다.

SELECT ObjectName = s.name + N'.' + o.name
    , ReservedPageCount = SUM(dps.reserved_page_count)
    , UsePageCount = SUM(dps.used_page_count)
FROM sys.schemas s
    INNER JOIN sys.objects o ON s.schema_id = o.schema_id
    INNER JOIN sys.partitions p ON o.object_id = p.object_id
    INNER JOIN sys.dm_db_partition_stats dps ON p.object_id = dps.object_id
WHERE s.name = N'dbo'
    AND o.name = N'MyTable'
GROUP BY s.name + N'.' + o.name;

2
실행 DBCC UPDATEUSAGE중 사용되지 않은 공간 및 사용되지 않은 페이지 수가 업데이트되었습니다. SQL Server에서보고하는 디스크 사용량과 페이지 정보가 완전히 동기화되지 않은 것 같습니다. 자세한 내용으로 게시물을 업데이트했습니다. 나는 이것이 처음에 어떻게 일어날 지 궁금하지만 적어도 문제가 발견되었습니다. 모든 도움에 감사드립니다. 정말 감사합니다!
Ken

0

열 중 하나는 이미지 유형의 LOB이며 크기는 몇 KB에서 수백 MB 사이 인 파일을 저장합니다.

내부 조각화가 발생했을 수 있습니다. 이 테이블
페이지 조각화 는 무엇입니까 ?
그리고 행 내 조각화는 행 외 페이지와 다른가?

몇 KB 파일이 있다고 가정합니다.
SQL Server는 모든 것을 8060 바이트 페이지에 저장합니다. 즉, 4040 바이트의 행 (또는 행 외부 데이터)이 있고 다음 행이 비슷한 경우 동일한 페이지에 둘 다 들어갈 수 없으므로 공간의 절반을 낭비하게됩니다. 가변 길이 열 (예 : 이미지로 시작)을 다른 테이블에 저장하여 행 크기를 변경하십시오.


조각화가 문제라고 생각하지 않습니다. 인덱스를 재 구축 한 후 클러스터 된 인덱스의 조각화는 0.45 %이고 페이지 충만도는 98.93 %입니다.
Ken

8KB 페이지에 잘 맞지 않는 매우 큰 행이나 LOB 데이터로 고통받는 경우 테이블이나 인덱스를 다시 작성해도 도움이되지 않습니다. Max Vernon은 "부분적으로 빈 페이지가 많이 있습니다."라고 더 자세하게 설명했습니다. 또한 내부 단편화라고
DrTrunks 벨

-3

데이터베이스가 전체 복구 모드입니까? 그렇다면 축소를 수행 할 때 모든 변경 사항이 기록되므로 예상 한대로 축소되지 않습니다. 작업 시간에 따라 백업을 수행하고 대량 배송 복구 모드로 전환 한 다음 데이터 파일 축소를 실행할 수 있습니다. 그런 다음 인덱스 스크립트를 실행하여 복구 / 재 구축하고 전체 복구로 다시 전환하려고합니다. 그것이 어쨌든 시도 할 것이지만 다시 말하지만,이 모든 작업에 대한 귀하의 영업 시간에 달려 있습니다.


4
복구 모델을 키우는 것은 흥미 롭습니다. OP가 로그 파일 크기에 문제가 있으면 더 적합 할 것이라고 생각 합니다. 그대로, 그들은 데이터 파일 의 크기에 문제가 있기 때문에 복구 모델이 설명 된 문제를 일으키는 경우 놀랍습니다.
Josh Darnell

사실이지만 축소를 실행하고 실제로 공간에 영향을 미치지 않는 유일한 시간은 복구 모델 때문 이었으므로 오진이 발생한 경우에 대비할 가치가 있다고 생각했습니다.
John-Henry Lochbaum

-3

DB를 축소하고 공간을 회수 할 수 없었던 유일한 시간은 DB가 생성 될 때 DB의 초기 크기 이상으로 DB를 축소 할 수 없기 때문입니다. 예를 들어 DB가 프로덕션 DB의 복사본이고 처음 525GB로 DB를 만든 경우 sql 서버는 DB에서 삭제하는 데이터의 양에 관계없이 525GB 이하로 크기를 줄일 수 없습니다. 그러나 DB가 383GB 미만으로 생성 된 후 525GB로 증가하면 공간을 확보하는 데 아무런 문제가 없습니다. 나는 이것이 Microsoft에 의한 어리 석고 자의적인 제한이라고 생각했습니다.

데이터베이스를 작성한 후 설정된 초기 크기까지만 데이터베이스를 축소하십시오.


문제는 데이터베이스 축소에 관한 것이 아닙니다 (그렇다면 데이터베이스 축소 기능은 초기 크기 영역 이후 사용 된 공간에 따라 다름)
eckes

사용되지 않는 공간이있는 한 원래 크기에 관계없이 데이터베이스를 몇 MB로 축소 할 수 있습니다. 반드시 좋은 아이디어는 아니지만 데이터베이스를 축소하고 이와 같은 한계에 도달하지 않는 경우가 많습니다.
Ray

-3

프로덕션 상자 에서이 문제가 발생하기 전에 각 테이블의 테이블과 인덱스를 순서대로 다시 작성해야합니다.

다음은 테이블을 확인하는 데 사용하는 쿼리입니다. 재 빌드해야하는 테이블을 판별하고 실행해야하는 SQL 조회를 작성하는 데 도움이됩니다. 이 쿼리는 사용되지 않은 공간이 1MB 이상이고 사용되지 않은 비율이 5 % 인 쿼리로 제한되므로 실제로 집중해야하는 항목 만 다시 작성하십시오.

SELECT  'alter table [' + t.NAME + '] rebuild;' AS SQL1, 'alter index all on [' + t.NAME + '] rebuild;' as SQL2, t.NAME AS TableName, p.rows AS RowCounts, SUM(a.total_pages) * 8/1024 AS TotalSpaceMB,  SUM(a.used_pages) * 8/1024 AS UsedSpaceMB,  (SUM(a.total_pages) - SUM(a.used_pages)) * 8/1024 AS UnusedSpaceMB, case when SUM(a.total_pages)=0 then 0 else (SUM(a.total_pages) - SUM(a.used_pages))*100/SUM(a.total_pages) end as Ratio  FROM     sys.tables t (nolock) INNER JOIN       sys.indexes i (nolock)  ON t.OBJECT_ID = i.object_id INNER JOIN  sys.partitions p (nolock) ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id INNER JOIN  sys.allocation_units a (nolock) ON p.partition_id = a.container_id LEFT OUTER JOIN  sys.schemas s (nolock) ON t.schema_id = s.schema_id WHERE  t.is_ms_shipped = 0 AND i.OBJECT_ID > 255  GROUP BY  t.Name, s.Name, p.Rows  
having  (SUM(a.total_pages) - SUM(a.used_pages)) * 8/1024>1
and (SUM(a.total_pages) - SUM(a.used_pages))*100/SUM(a.total_pages)>5
ORDER BY    5 desc

OP 상태에 따라 테이블을 다시 작성하면 대부분의 조각화가 제거됩니다. 다른 재 구축을하면 더 도움이 될 것 같습니다.
Max Vernon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.