행 기반 스토리지에서 불필요한 컬럼 읽기가 만드는 병목

행 기반 스토리지의 불필요한 컬럼 읽기 문제와 열 기반 저장 방식의 차이, 쿼리 최적화 전략을 정리한다.

2026-08-14 · 최초 발행 2025-08-10

레코드 전체를 읽는 저장 구조가 분석 쿼리에 미치는 영향

행 기반 스토리지는 데이터를 레코드 단위로 연속 저장한다. Oracle, MS SQL Server, MySQL 같은 전통적인 RDBMS에서 주로 쓰이며, 특정 레코드를 찾아 처리하는 트랜잭션 작업에 잘 맞는다.

이 방식은 랜덤 액세스와 레코드 단위 인덱스 구성에 유리하고, 데이터 중복도 상대적으로 적다. 반면 분석 쿼리가 일부 컬럼만 요구하더라도 해당 레코드의 나머지 컬럼까지 함께 읽게 되는 경우가 있다.

그 부담은 디스크 I/O에만 머물지 않는다. 필요하지 않은 데이터가 버퍼 캐시를 차지하고, 클라이언트와 서버 사이의 전송량 및 추가 처리에 필요한 CPU 사용량도 늘어난다.

같은 집계 쿼리를 행과 열로 읽는 방식

다음과 같은 Customers 테이블을 가정한다.

  • customer_id
  • name
  • address
  • phone
  • email
  • registration_date
  • last_purchase_date
  • credit_score
  • loyalty_points

분석 쿼리는 가입일 조건을 걸고 포인트 평균만 계산한다.

SELECT AVG(loyalty_points)
FROM Customers
WHERE registration_date > '2020-01-01';

행 기반 접근에서는 먼저 registration_date > '2020-01-01' 조건에 맞는 레코드를 찾은 뒤, 대상 레코드마다 9개 컬럼을 모두 읽고 loyalty_points만 꺼내 평균을 계산한다. 이 과정에서 필요하지 않은 7개 컬럼도 메모리와 I/O를 사용한다.

열 기반 접근은 registration_date에서 조건에 맞는 레코드 위치를 찾고, 그 위치에 대응하는 loyalty_points 데이터만 읽어 평균을 계산한다. 필요한 데이터 범위가 좁아지는 만큼 I/O와 메모리 사용도 줄일 수 있다.

필요한 데이터 비율이 메모리 사용량을 바꾸는 경우

1000만 레코드의 테이블에서 레코드 하나가 1KB이고, 실제로 필요한 컬럼이 전체의 10%라고 가정한다.

행 기반 스토리지는 다음 데이터를 읽는다.

  • 읽어야 할 데이터: 10,000,000 * 1KB = 10GB

열 기반 스토리지는 필요한 컬럼 비율만 읽는다.

  • 읽어야 할 데이터: 10,000,000 _ (1KB _ 10%) = 1GB

두 방식 사이에는 9GB의 메모리 사용량 차이가 발생한다.

쿼리 요청디스크에서 데이터 읽기메모리로 데이터 로드필요한 컬럼 추출계산 처리결과 반환

빨간색으로 표시한 구간은 행 기반 스토리지에서 불필요한 컬럼을 함께 읽으며 추가 시간이 들 수 있는 지점이다.

측정값이 보여주는 워크로드별 차이

대규모 데이터 웨어하우스 환경의 측정 결과는 다음과 같다.

Query Type 행기반 (seconds) 열기반 (seconds)
Single Record Lookup 0.01 0.05
Specific Column Aggregation 15 2
Range Condition Aggregation 25 3
Full Table Scan 30 10

(막대 순서: 행 기반, 열 기반)

단일 레코드 조회에서는 행 기반이 더 효율적이지만, 특정 컬럼 집계·범위 조건 집계·전체 테이블 스캔에서는 열 기반 스토리지가 더 나은 성능을 보인다. 저장 방식을 고를 때 OLTP와 OLAP의 성격을 분리해 볼 이유가 여기에 있다.

행 기반 데이터베이스에서 읽기 범위를 줄이는 방법

쿼리가 실제로 사용하는 컬럼만 선택하는 것부터 시작할 수 있다.

-- 피해야 할 쿼리
SELECT * FROM Customers WHERE customer_id = 1001;

-- 최적화된 쿼리
SELECT name, email FROM Customers WHERE customer_id = 1001;

테이블을 논리적으로 나눠 필요한 파티션에만 접근하도록 설계하는 방법도 있다.

CREATE TABLE sales (
    sale_id INT,
    product_id INT,
    sale_date DATE,
    amount DECIMAL(10,2)
) PARTITION BY RANGE (YEAR(sale_date)) (
    PARTITION p0 VALUES LESS THAN (2019),
    PARTITION p1 VALUES LESS THAN (2020),
    PARTITION p2 VALUES LESS THAN (2021),
    PARTITION p3 VALUES LESS THAN (2022)
);

커버링 인덱스를 이용하면 테이블을 읽지 않고 인덱스만으로 필요한 결과를 얻을 수 있다.

CREATE INDEX idx_customer_email_name ON Customers(customer_id, email, name);

-- 이 쿼리는 테이블에 접근하지 않고 인덱스만으로 해결 가능
SELECT name, email FROM Customers WHERE customer_id = 1001;

일부 RDBMS는 행 기반 테이블 위에 열 기반 인덱스를 제공한다. MS SQL Server의 컬럼스토어 인덱스가 그 예다.

CREATE COLUMNSTORE INDEX ix_cs_sales ON Sales
(sale_date, product_id, amount);

트랜잭션과 분석을 분리하는 혼합 아키텍처도 선택지다. OLTP 작업은 행 기반 스토리지에서 처리하고, OLAP 작업은 열 기반 스토리지에 맡긴다.

저장 방식은 쿼리 패턴을 따라간다

기반 스토리지컬럼 단위 저장OLAP에 최적화집계 쿼리 유리높은 압축률데이터 수정 비효율적 기반 스토리지레코드 단위 저장OLTP에 최적화단일 레코드 액세스 유리데이터 삽입/수정 효율적불필요한 컬럼 읽기 문제

행 기반 스토리지는 OLTP 환경에서 중요한 역할을 하지만, 일부 컬럼만 읽는 분석 작업에서는 불필요한 컬럼 읽기가 성능 저하로 이어질 수 있다. 트랜잭션 처리는 행 기반 시스템에서, 분석과 보고서 생성은 열 기반 시스템으로 복제한 데이터에서 처리하는 혼합 방식도 사용된다.

시스템 요구사항과 쿼리 패턴을 기준으로 저장 구조와 최적화 전략을 정해야 불필요한 컬럼 읽기를 줄일 수 있다.

행 기반 스토리지열 기반 스토리지쿼리 최적화OLTPOLAP