개발 & 서버/MSSQL

📌 MSSQL 한 줄 INSERT할 때 실제 DB 용량은 얼마나 늘어날까?

pandada 2025. 5. 22. 15:16
반응형

 

개발하다 보면 한 줄씩 데이터가 쌓일 때 실제 DB 크기가 얼마나 증가하는지 궁금할 때가 있다.
저도 그런 상황이 생겨서 직접 확인해봤습니다.

 

우선 대략적인 증가 용량에 대한 공식부터 확인해보자.


📌 1. 증가 용량 추정 공식

고정 길이 데이터 + 가변 길이 데이터 + Row overhead

✅ 2. 계산 요소

항목 설명
고정 길이 데이터 INT, DATETIME, MONEY, FLOAT, CHAR(n) 등
가변 길이 데이터 VARCHAR(n), NVARCHAR(n), TEXT, XML 등
Row overhead 보통 7~11바이트 정도의 관리용 메타데이터 공간
Page 구조 1 Page = 8KB, 1 Page에 여러 row가 들어감
할당 단위 실제 파일 크기는 Page 단위로 커짐 (8KB씩), 내부적으로는 64KB extent 단위로 증가

3. 예시 계산
CREATE TABLE Test (
  ID INT,                        -- 4 bytes
  Name NVARCHAR(50),            -- 최대 100 bytes (UTF-16)
  Description NVARCHAR(1000),   -- 최대 2000 bytes
  RegDate DATETIME              -- 8 bytes
)

 

예시 1건 입력 시:
  • 고정길이: ID(4) + DATETIME(8) = 12 bytes
  • 가변길이: NVARCHAR(50) + NVARCHAR(1000)
    → 입력값에 따라 다르지만, 최대치 기준 2100 bytes
  • Row overhead: 약 10 bytes

총 합: 약 12 + 2100 + 10 = 2122 bytes (대략 2.07KB)

※ 단, 실제로는 row 압축, page fragmentation, 기타 인덱스 등에 따라 달라짐


✅ 4. 실제 확인 방법 (테스트 후 측정)

-- 1. 현재 DB 사용량 확인
EXEC sp_spaceused 'Test'

-- 2. 10,000건 INSERT
INSERT INTO Test(ID, Name, Description, RegDate)
SELECT TOP (10000)
    ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
    N'TestName',
    N'TestDescription TestDescription TestDescription...',
    GETDATE()
FROM master..spt_values a, master..spt_values b

-- 3. 다시 확인
EXEC sp_spaceused 'Test'

🔎 요약

상황예상 증가 용량
단순 테이블, 고정형 필드 50~100 bytes / row
가변 문자열 포함 1~2KB / row
대용량 텍스트, BLOB 수 KB ~ 수 MB / row
실제 DB 파일 증가 8KB Page 기준, 여유 공간 있으면 즉시 증가 안 할 수도 있음

✅ Insert 스크립트

DECLARE @i INT = 0;

WHILE @i < 100
BEGIN
    INSERT INTO your_table_name (id, name, Description, RegDate)
    VALUES (
        @i,
        'TestName',
        'TestDescription TestDescription TestDescription...',
        DATEADD(SECOND, @i, '2025-05-22T13:18:00')
    );
    SET @i += 1;
END;

 

그럼 이제 인덱스, page fragmentation 및 가변에 대해서도 추가적으로 확인해보자.


✅ page fragmentation, 기타 인덱스에 따른 내용

"한 줄(row)을 넣으면 DB 용량이 얼만큼 늘어날지 계산은 가능하지만,
실제로는 아래 같은 요소들이 있어서 정확히 딱 정해진 값으로 늘어나진 않다."


📦 왜 그런지? → 주요 원인

요소 설명
Row 압축 (Row Compression) SQL Server가 저장 공간을 줄이려고 데이터를 압축해서 넣는 경우. 예: INT → 4바이트인데 1만 써도 1바이트만 쓸 수도 있음
Page Fragmentation (페이지 조각화) 데이터가 SQL Server 내부에서는 8KB 단위(Page)로 저장됨. 비어 있는 페이지에 끼워 넣다 보면 공간 낭비가 생길 수 있음
인덱스 데이터를 빠르게 찾기 위한 구조인데, 인덱스도 공간을 차지함. 데이터를 넣으면 인덱스에도 같이 들어감 → 추가 공간 필요

✅ 1. Row 압축 (Row Compression)

🧠 설명:

SQL Server는 Row Compression 기능이 켜져 있으면, 실제 값이 작을 경우 데이터 타입보다 작은 크기로 저장한다.

📌 예시:

CREATE TABLE Test1 ( id INT, flag BIT );
  • INT는 원래 4바이트지만, 값이 0~255 사이면 압축으로 1~2바이트만 사용 가능
  • BIT는 1바이트 안에서 여러 값이 압축됨 (8개까지)

💡 결과:

예상 용량: 4 + 1 = 5바이트
압축 후: 1~3바이트로 줄어들 수 있음


✅ 2. Page Fragmentation (페이지 조각화)

🧠 설명:

SQL Server는 데이터를 8KB 페이지 단위로 저장하는데, 중간에 빈 공간이 생기면 데이터가 여러 페이지로 나뉘어서 저장될 수 있어다.

📌 예시:

  • A, B, C 데이터를 순서대로 저장
  • 나중에 A와 B 사이에 D를 넣으면 → 기존 공간이 꽉 차 있으면 새 페이지로 넘어가면서 공간 낭비

💡 결과:

  • 한 줄당 1KB 데이터인데, 실제로는 8KB가 추가될 수 있음 (새 페이지 할당)

✅ 3. 인덱스(Index)

🧠 설명:

인덱스가 걸려 있으면 데이터를 INSERT할 때 인덱스도 함께 업데이트돼요. 이 과정에서 추가 공간이 소모됨.

📌 예시:

CREATE TABLE Test2 ( 
	id INT PRIMARY KEY, -- 클러스터형 인덱스 생성됨
	name VARCHAR(100)
);
INSERT INTO Test2 VALUES (1, 'Kim');
  • 인덱스가 없으면: 1건만 저장
  • 인덱스가 있으면: 데이터 + 인덱스 트리에도 반영 → 실제 공간 2배 이상 증가 가능

✅ 4. NULL / VARCHAR / NVARCHAR

🧠 설명:

가변 길이 문자형(VARCHAR, NVARCHAR)은 입력한 데이터 길이에 따라 실제 저장 공간이 다름.
NULL은 공간 거의 안 차지하고, 긴 문자열은 크게 차지함.

📌 예시:

CREATE TABLE Test3 ( content NVARCHAR(1000) );
  • INSERT INTO Test3 VALUES (NULL); → 거의 공간 사용 안 함
  • INSERT INTO Test3 VALUES (REPLICATE(N'A', 1000)); → 최대 2000바이트 사용

🔎 요약표:

요소 INSERT 1건 예상 실제 증가 가능 공간 설명
Row 압축 5~10바이트 2~5바이트 값 작으면 압축
페이지 조각화 1KB 최대 8KB 새 페이지 할당 시
인덱스 100바이트 100~300바이트 인덱스 구조까지 반영
VARCHAR 0~1000바이트 값 길이에 따라 다름 짧으면 공간 적게 차지

📌 정리

  • 계산한 데이터 크기 ≠ 실제 증가한 DB 용량
  • 내부적으로 SQL Server가 데이터를 압축하거나, 중간에 비효율적으로 넣거나, 인덱스를 자동 갱신하면서 예상보다 더 많이 또는 적게 용량이 늘어날 수 있다는 뜻이다.
반응형

 

그럼 이제 진짜 확인을 위해서 실제 샘플 테이블을 만들고 내용을 한번 확인해보자.

 

예시로 사용한 테이블은 CP_Table 라는 테이블.

✅ 테이블 구조

컬럼명 데이터 타입 비고
num INT PK, 자동 증가
note_num INT 노트 번호
user_num INT 사용자 번호
note_date DATETIME 노트 시간
h_type NVARCHAR(15) 노트 유형 (예: view, print 등)
contents NTEXT 내용 (긴 텍스트 저장용)
  • num은 클러스터형 PK로 인덱스가 걸려 있고,
  • h_type은 짧은 문자열,
  • contents는 NTEXT라 별도 저장됩니다.

✅ MSSQL에서 한 줄 데이터가 차지하는 공간은?

예상하기 쉽게 각 컬럼이 차지하는 용량을 정리.

항목 용량 (대략)
num, w_num, user_num 4바이트씩 → 총 12바이트
w_date 8바이트
h_type (NVARCHAR(15)) 최대 32바이트 (2바이트 × 15 + 오버헤드)
contents (NTEXT) 본문에는 16바이트 포인터만 저장됨
Row 오버헤드 7~11 바이트 정도

📌 contents가 NULL이면 → 총 약 75~80바이트

📌 contents에 값이 있을 경우 → 내용 길이에 따라 추가로 증가

 

예시로 몇 개 비교하면:

contents 길이 실제 예상 용량 증가
NULL 약 80바이트
1KB 텍스트 약 1.08KB
10KB 텍스트 약 10.08KB
100KB 텍스트 약 100.08KB

📌 NTEXT는 별도 텍스트 페이지에 저장되기 때문에, row 자체는 항상 16바이트만 가지고 있음.


✅ 압축이나 기타 요소는?

위에서 생선한 테이블(CP_Table)은 현재 압축 기능이 없음(NONE) 상태이고,
추가 인덱스도 없이 PK 하나만 적용되어 있어서 예측하기 쉬운 구조.

 

하지만 실제 운영 환경에서는 다음 요소들도 공간에 영향을 줍니다:

  • Row Compression: 숫자나 null이 많을 경우 압축되어 작게 저장
  • Page Fragmentation: 중간에 빈 공간이 생기면 페이지 낭비 발생
  • 인덱스: 인덱스 구조에 따라 INSERT 시 추가 공간 사용됨
  • Page 단위 저장: 1건 저장했다고 바로 .mdf 용량이 증가하는 건 아님 (8KB 단위)

✅ 실제 위의 테이블에서 100건 / 1000건 데이터 넣었을 때의 용량 비교

  • 기존 용량

  • 100건 INSERT 후 용량

  • 1000건 INSERT 후 용량


✅ 마무리

정리하면, 한 줄 INSERT한다고 바로 .mdf가 늘어나진 않지만,
Row 단위로 보면 평균 80바이트 + contents 길이만큼 추가라고 보면 된다.

운영 환경에서 용량 계산하거나, 테이블 사이즈 추정할 때 참고하면 좋을 것 같아서 정리해봤습니다.
저처럼 궁금하셨던 분들께 도움이 되길 🙌

반응형