Data Engineering/Data Infra & Process

[10편] 대규모 벡터 데이터 관리 (샤딩 & 메모리 최적화)

ygtoken 2025. 3. 7. 15:59
728x90

 

이 글에서는 PostgreSQL pgvector를 활용하여 대규모 벡터 데이터를 효율적으로 저장하고 관리하는 방법을 다룹니다.

특히, 샤딩(Sharding), 테이블 파티셔닝(Partitioning), 메모리 최적화(shared_buffers, work_mem 등) 을 통해 성능을 극대화하는 방법을 설명합니다.

 

대량 벡터 데이터를 저장하는 방법 (샤딩 & 파티셔닝 적용)

PostgreSQL 메모리 최적화 (shared_buffers, work_mem)

빠른 검색을 위한 저장소 엔진 및 인덱싱 전략

 


🚀 1. 대량 벡터 데이터 저장 전략: 샤딩(Sharding) vs 파티셔닝(Partitioning)

 

벡터 데이터는 보통 수십만~수억 개 이상의 벡터를 저장해야 합니다.

PostgreSQL에서 효율적인 데이터 관리를 위해 샤딩(Sharding)과 파티셔닝(Partitioning)을 활용할 수 있습니다.

 

🔹 1️⃣ 샤딩(Sharding)

 

샤딩은 데이터를 여러 개의 독립적인 데이터베이스(서버)에 분산 저장하는 방식입니다.

장점: 한 서버에 너무 많은 데이터를 저장할 필요 없이 수평 확장 가능

단점: 다중 노드 관리가 필요하고, 데이터 조인이 어려움

 

✔️ 샤딩 적용 방식

1️⃣ PostgreSQL Foreign Data Wrapper (FDW): 여러 개의 PostgreSQL 인스턴스를 연결하여 데이터 분산

2️⃣ Citus 확장: PostgreSQL의 수평 확장을 지원하는 오픈소스 확장 기능

 

📌 Citus를 활용한 샤딩 적용

-- 확장 기능 활성화
CREATE EXTENSION citus;

-- 벡터 데이터를 저장할 샤드 테이블 생성
CREATE TABLE embeddings (
    id SERIAL PRIMARY KEY,
    content TEXT,
    embedding vector(1536)
);

-- 샤딩 적용
SELECT create_distributed_table('embeddings', 'id');

샤딩을 통해 여러 개의 노드에 벡터 데이터를 자동으로 분산

 


🔹 2️⃣ 파티셔닝(Partitioning)

 

파티셔닝은 하나의 데이터베이스에서 테이블을 여러 개로 나누어 저장하는 방식

장점: 데이터 조회 시 특정 파티션만 검색하여 성능 향상

단점: 수평 확장이 어렵고, 단일 서버에 종속됨

 

📌 PostgreSQL pgvector 테이블을 날짜 기준으로 파티셔닝 적용

CREATE TABLE embeddings (
    id SERIAL,
    content TEXT,
    embedding vector(1536),
    created_at TIMESTAMP NOT NULL DEFAULT now()
) PARTITION BY RANGE (created_at);

-- 월 단위로 데이터 파티셔닝
CREATE TABLE embeddings_2024_01 PARTITION OF embeddings
    FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');

CREATE TABLE embeddings_2024_02 PARTITION OF embeddings
    FOR VALUES FROM ('2024-02-01') TO ('2024-03-01');

데이터를 특정 날짜 범위로 자동 분할하여 검색 속도를 향상

 


🚀 2. PostgreSQL 메모리 최적화 (shared_buffers, work_mem)

 

🔹 1️⃣ shared_buffers 설정

 

shared_buffers는 PostgreSQL이 데이터를 캐싱하는 메모리 크기를 지정하는 파라미터입니다.

✅ 기본값은 128MB이지만, 전체 시스템 메모리(RAM)의 25~40%로 설정하는 것이 권장됩니다.

 

📌 설정 예시 (4GB 설정)

primary:
  postgresqlConfiguration:
    shared_buffers: "4GB"

 

pg_stat_bgwriter로 shared_buffers 사용량 확인

SELECT * FROM pg_stat_bgwriter;

 

 


🔹 2️⃣ work_mem 설정

 

work_mem쿼리 실행 중 사용할 수 있는 임시 메모리 크기를 설정하는 파라미터입니다.

✅ 기본값은 4MB이지만, 벡터 검색에서는 최소 64MB 이상으로 설정하는 것이 좋습니다.

 

📌 설정 예시 (128MB 설정)

primary:
  postgresqlConfiguration:
    work_mem: "128MB"

 

실제 work_mem 설정 확인

SHOW work_mem;

 

 


🔹 3️⃣ effective_cache_size 설정

 

effective_cache_size는 PostgreSQL이 OS의 캐시 메모리를 얼마나 활용할지 결정하는 파라미터입니다.

✅ 기본값은 너무 작게 설정되어 있어, 전체 시스템 메모리의 50~75%로 설정하는 것이 좋습니다.

 

📌 설정 예시 (8GB 설정)

primary:
  postgresqlConfiguration:
    effective_cache_size: "8GB"

 

현재 설정 확인

SHOW effective_cache_size;

 

 


🚀 3. 빠른 벡터 검색을 위한 저장소 엔진 & 인덱스 적용

 

🔹 1️⃣ pgvector 인덱스 최적화 (HNSW & IVFFlat)

 

대규모 벡터 데이터를 검색할 때는 HNSW(Hierarchical Navigable Small World) 또는 IVFFlat(Indexed Flat) 인덱스를 활용하여 속도를 높일 수 있습니다.

 

📌 HNSW 인덱스 적용

CREATE INDEX embeddings_hnsw ON embeddings USING hnsw (embedding vector_l2_ops);

 

📌 IVFFlat 인덱스 적용 (백만 개 이상의 벡터 데이터에 적합)

CREATE INDEX embeddings_ivfflat ON embeddings USING ivfflat (embedding vector_l2_ops)
WITH (lists = 100);

lists 값을 조정하여 성능 최적화 가능

HNSW는 정확도가 높지만 메모리 사용량이 많고, IVFFlat은 속도가 빠르지만 정확도가 낮음

 


🔹 2️⃣ pgvector 검색 속도 비교

검색 방식평균 응답 속도 (100만 개 벡터)

기본 ORDER BY <-> 검색 3~5초
HNSW 인덱스 적용 후 50~200ms
IVFFlat 인덱스 적용 후 10~50ms

 

 


📌 4. 최종 정리

 

대규모 벡터 데이터를 저장하는 전략 (샤딩 & 파티셔닝 적용)

PostgreSQL 메모리 최적화 (shared_buffers, work_mem, effective_cache_size)

빠른 검색을 위한 저장소 엔진 및 인덱싱 전략 (HNSW, IVFFlat)

728x90