사용되지 않은 공간 SQL Server 테이블 해제


11

SQL Server 2012 Express에 사용되지 않은 공간이 많은 테이블이 있습니다.

데이터베이스의 공간을 확보해야합니다.

| 이름 | ROWS | 예약 됨 | 데이터 | INDEX_SIZE | 미사용 |
| ------------- | -------- | ----------------------------- --- | ------------ | -------------- |
| MyTableName | 158890 | 8928296 KB | 5760944 KB | 2248 KB | 3165104 KB |

SQL에서 3165104KB를 릴리스하려면 어떻게해야합니까?

나는 이미 시도했다 :

Alter table MyTableName Rebuild
DBCC CLEANTABLE (MyDbName,"MyTableName ", 0)
ALTER INDEX ALL ON MyTableName REORGANIZE ; 
ALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF) 

다음은 테이블입니다.

CREATE TABLE [dbo].[MyTableName](
    [ImageID] [int] IDENTITY(1,1) NOT NULL,
    [DateScan] [datetime] NULL,
    [ScanImage] [image] NULL,
 CONSTRAINT [PK_Image] PRIMARY KEY CLUSTERED 
(
    [ImageID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

우리가 한 유일한 일은 ScanImage모든 행에서 훨씬 더 작은 이미지 로 대체 됩니다 (이것은 사용되지 않은 공간이 얼마나 많은 지입니다).

답변:


10

우리가 한 유일한 일은 ScanImage모든 행에서 훨씬 더 작은 이미지 로 대체 됩니다 (이것은 사용되지 않은 공간이 얼마나 많은 지입니다)

몇 가지 실험을 통해 가장 공간 효율적인 방법은 할당 단위를 삭제하고 다시 채우는 것입니다 (유지 관리 창이있는 경우).

문제의 테이블 구조로 나를 위해 최고의 공간 축소를 달성 한 예제 코드는 다음과 같습니다.

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

SET XACT_ABORT ON;

BEGIN TRAN

SELECT [ImageID],
       [ScanImage]
INTO   #Temp
FROM   [dbo].[MyTableName]

ALTER TABLE [dbo].[MyTableName]
  DROP COLUMN [ScanImage]

/*Allocation unit not removed until after this*/
ALTER INDEX PK_Image ON MyTableName REBUILD

ALTER TABLE [dbo].[MyTableName]
  ADD [ScanImage] IMAGE NULL

UPDATE [dbo].[MyTableName]
SET    [ScanImage] = T.[ScanImage]
FROM   [dbo].[MyTableName] M
       JOIN #Temp T
         ON M.ImageID = T.[ImageID]

DROP TABLE #Temp

COMMIT 

모든 것이 트랜잭션에 있으므로 기계가 충돌하면 롤백됩니다. 아마도 약간의 오류 처리 또는 적어도 할 수 SET XACT_ABORT ON있습니다. 나는 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;복사 중이나 후에 동시 수정이 발생하지 않고 손실 되는 것을 막았습니다.

image모든 행에서 크기를 줄인 후 예약 된 LOB 페이지 수는 다음과 같습니다.

+ ------------------------------------------------- -+ --------------------- + ------------------------- +
| 이벤트 | lob_used_page_count | lob_reserved_page_count |
+ ------------------------------------------------- -+ --------------------- + ------------------------- +
| 각각 100,000 바이트의 데이터로 10,000 개의 행 삽입 | 135005 | 135017 |
| 모든 행을 10,000 바이트 이미지 데이터로 갱신 | 31251 | 135012 |
| 재구성 | 23687 | 25629 |
| 이미지 데이터 삭제 및 다시 추가 | 13485 | 13489 |
+ ------------------------------------------------- -+ --------------------- + ------------------------- +

1
또는 테이블이 크면 유지 관리 기간 동안 데이터를 BCP 출력 한 다음 BULK INSERT를 다시 입력합니다.
Kin Shah

6

시험

ALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF)

이렇게하면 클러스터형 인덱스가 다시 만들어 지므로 작업을 완료하려면 데이터베이스에 추가 공간이 필요합니다. 디스크가 가득 차서 여유 공간이없는 경우 새 데이터 파일을 다른 디스크의 데이터베이스에 추가하고 테이블을 이동할 수 있습니다.

클러스터 된 인덱스가 100 % 미만의 FILLFACTOR로 정의 될 수도 있습니다. 채우기 비율을 예를 들어 66 %로 설정하면 나중에 사용할 수 있도록 각 데이터 페이지의 1/3을 비워 둡니다. 이것이 문제라면 다음을 사용하여 채우기 비율을 수정할 수 있습니다ALTER INDEX PK_Image ON MyTableName REBUILD WITH (ONLINE = OFF, FILLFACTOR=100)

최근에 테이블에서 가변 길이 필드를 삭제 한 경우 시도해 볼 수도 있습니다 DBCC CLEANTABLE( Databasename, "MyTableName")

온라인 설명서 (BOL)에는 http://technet.microsoft.com/en-us/library/ms188388%28v=sql.100%29.aspx의 인덱스 재 구축에 대한 훌륭한 기사가 있습니다.


2

DB 복구 모드가인지 확인하십시오 SIMPLE.

열을로 변경하십시오 VARBINARY(MAX).

그런 다음 데이터를 완전히 새로운 테이블로 복사하십시오.

을 사용하여 새 테이블 크기를 확인하십시오 sp_spaceused "tablename". 사용되지 않은 테이블 공간에 만족하면 테이블 이름을 지정하지 않고 동일한 명령을 사용하여 데이터베이스의 사용되지 않은 공간을 확인하십시오. 이 공간은 여전히 ​​데이터베이스 파일 내에 있으며 OS로 릴리스되지 않습니다.

원래 테이블을 삭제하고 새 테이블의 이름을 바꾸거나 동일한 작업을 다시 수행하고 이름 바꾸기 작업을 신뢰할 수없는 경우 원래 테이블 이름을 사용할 수 있습니다 (완전히 신뢰할 수 없음).

이것이 작동하면 마지막 단계는 쉽습니다. 파일을 축소하고 사용하지 않는 공간을 해제하는 방법을 알고 있습니다.

외래 키가 있으면 정의를 기록하고 삭제하고 위에서 언급 한 작업을 수행 한 후 외래 키를 다시 만드십시오. 물론 이것은 시간이 걸리며이 작업은 오프 타임에 수행되어야합니다. 이 전체 작업은 스크립트를 통해 수행하여 밤새 실행할 수 있습니다.


1

새 데이터베이스를 만들고 데이터를 복사합니다. 가져 오기 / 내보내기 마법사를 사용할 수 있어야합니다. (백업 및 복원으로 문제가 계속 발생합니다.) 데이터 가져 오기 결과를 확인하십시오. 모두보기 좋으면 원래 데이터베이스의 이름을 바꾼 다음 새 데이터베이스의 이름을 사용하려는 이름으로 바꾸십시오. (저는 온라인을 다시 한 번 확인하기 위해 원본을 떨어 뜨리기 전에 항상 조금 기다립니다.)

그만한 가치가 있기 때문에 데이터베이스가 너무 크지 않은 경우 다음 단계를 통해 데이터베이스의 공간 공간을 확보했습니다. 그러나 SQL Server Express를 사용하고 있으므로이 작업을 수행 할 공간이 없을 수 있습니다.

  1. 파일 그룹에 새 파일을 추가하십시오.
  2. 를 실행하십시오 DBCC SHRINKFILE(file, EMPTYFILE). 시스템 메타 데이터를 이동할 수 없으므로 MDF를 축소하므로 결국 실패합니다. 그러나 빈 Blob 할당은 이동되지 않습니다.
  3. 를 실행하십시오 DBCC SHRINKFILE(newfile,EMPTYFILE). 이렇게하면 초과 공간을 뺀 데이터가 다시 이동합니다.
  4. 파일 그룹에서 새 파일 (현재 비어 있음)을 삭제하십시오.

이것은 얼룩을 제거합니다. 업그레이드 스크립트 테스트를 위해 주로 비어있는 데이터베이스를 작성하기 위해이 기술을 주로 사용했다고 언급해야합니다.


-1

클러스터 된 인덱스를 재구성하십시오. 하나는 노드에 데이터를 가지고 있으므로 조각화 될 수 있습니다.


실행을 시도했습니다 : ALTER INDEX ALL ON [MyTableName] REORGANIZE;
DermFrench

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