본문 바로가기

DB

텍스트 임베딩을 저장하는 최고의 방법: Parquet와 Polars 활용하기

728x90
반응형

📌 임베딩 데이터를 저장하는 최적의 방법은?

최근 AI 기술의 발전과 함께 텍스트 임베딩(Text Embeddings) 이 점점 더 중요한 역할을 하고 있습니다.
임베딩은 텍스트 데이터를 고차원 벡터로 변환한 것으로, 이를 활용하면 유사한 의미를 가진 텍스트를 쉽게 비교 하거나 빠르게 검색할 수 있는 기능 을 구현할 수 있습니다.
하지만 한 가지 문제점이 있습니다.
"임베딩 데이터를 효과적으로 저장하고 빠르게 검색하려면 어떻게 해야 할까?"
많은 사람들은 CSV, Pickle, Numpy 배열 같은 방법을 사용하지만, 이 방법들은 저장 공간을 많이 차지하고 속도도 비효율적입니다.
더 좋은 방법은 없을까요?
이 글에서는 Parquet 파일과 Polars 라이브러리를 활용한 최적의 임베딩 저장 방법 을 소개합니다.
이를 통해 효율적인 데이터 저장, 빠른 검색, 그리고 실용적인 활용법까지 모두 알아볼 수 있습니다.

반응형

🧐 임베딩 데이터 저장 방식과 문제점

임베딩을 저장하는 방법은 여러 가지가 있지만, 기존 방법들은 단점이 많습니다.

1️⃣ CSV 파일: 간단하지만 비효율적

CSV 파일은 가장 직관적인 방법이지만, 다음과 같은 문제점이 있습니다.
✔ 숫자를 텍스트로 변환하여 저장하기 때문에 파일 크기가 커짐
✔ 데이터를 불러올 때 다시 숫자로 변환해야 해서 속도가 느림
✔ 다차원 배열(임베딩 데이터) 저장이 어려움
📌 예제 코드 (CSV 저장 및 불러오기)

import numpy as np
import pandas as pd

# 랜덤한 768차원 임베딩 데이터 생성
embeddings = np.random.rand(10000, 768).astype(np.float32)

# CSV 파일로 저장
df = pd.DataFrame(embeddings)
df.to_csv("embeddings.csv", index=False)

# CSV 파일 불러오기
df = pd.read_csv("embeddings.csv")
embeddings = df.values.astype(np.float32)

이 방식은 데이터가 많아질수록 불필요한 변환 비용 이 증가하고 속도가 느려집니다.


2️⃣ Pickle 파일: 빠르지만 비효율적인 방식

Pickle은 Python 객체를 그대로 저장하는 방식입니다.
CSV보다 저장 속도는 빠르지만, 몇 가지 문제점이 있습니다.
보안 문제: Pickle 파일은 임의의 코드 실행이 가능하여 위험함
이식성 부족: 다른 언어에서 사용하기 어려움
데이터 검색 불가능: 저장된 데이터를 빠르게 검색할 수 없음


3️⃣ Numpy 파일(.npy): 빠르지만 메타데이터 저장이 어려움

Numpy 배열을 그대로 저장하는 방식도 있습니다.

np.save("embeddings.npy", embeddings)
embeddings = np.load("embeddings.npy")

✔ 빠르고 효율적이지만, 메타데이터(예: 문장 ID, 태그 등)를 함께 저장하기 어려움
✔ 데이터 필터링 및 검색 기능이 부족함


🚀 Parquet와 Polars: 더 나은 대안

Parquet 파일이란?

Parquet는 Apache에서 개발한 컬럼형 저장 방식의 파일 포맷 입니다.
CSV와 달리 숫자를 압축된 바이너리 형태로 저장하여 파일 크기를 줄이고 속도를 향상 시킬 수 있습니다.
빠른 저장 및 로딩 속도
저장 공간 절약 (CSV 대비 5~10배 더 효율적)
컬럼별 저장이 가능하여 검색 속도 증가
📌 예제 코드 (Parquet 저장 및 불러오기)

import pandas as pd

df = pd.DataFrame({"id": range(10000), "embedding": list(embeddings)})
df.to_parquet("embeddings.parquet", index=False)

# 불러오기
df = pd.read_parquet("embeddings.parquet")
embeddings = np.vstack(df["embedding"].to_numpy())

Polars 라이브러리를 활용한 고속 데이터 처리

Polars는 Pandas보다 10배 이상 빠른 속도 를 제공하는 데이터 프레임 라이브러리입니다.
특히 Parquet와 함께 사용하면 큰 데이터도 빠르게 처리 할 수 있습니다.
Pandas보다 훨씬 빠른 속도
Zero-Copy 지원 → 메모리 효율적 사용
복잡한 데이터 필터링도 쉽고 빠름
📌 Polars를 활용한 Parquet 파일 저장 및 로딩

import polars as pl

df = pl.DataFrame({"id": range(10000), "embedding": embeddings.tolist()})
df.write_parquet("embeddings.parquet")

# 불러오기
df = pl.read_parquet("embeddings.parquet")
embeddings = np.array(df["embedding"].to_list(), dtype=np.float32)

이제 데이터 로딩 속도가 훨씬 빨라지고, 파일 크기도 줄어든다 는 것을 확인할 수 있습니다.


🏎 빠른 유사도 검색(dot product 활용)

임베딩 데이터를 저장하는 것뿐만 아니라, 빠르게 검색하는 것도 중요 합니다.
보통 벡터 데이터베이스를 사용하지만, 작은 프로젝트에서는 Polars와 Numpy를 활용하여 빠르게 검색할 수도 있습니다.

def fast_dot_product(query, matrix, k=3):
    dot_products = query @ matrix.T
    idx = np.argpartition(dot_products, -k)[-k:]
    idx = idx[np.argsort(dot_products[idx])[::-1]]
    return idx, dot_products[idx]

# 예제: 특정 임베딩과 가장 유사한 3개 찾기
query_embedding = embeddings[0]
idx, scores = fast_dot_product(query_embedding, embeddings, k=3)
print(f"유사한 임베딩 인덱스: {idx}, 점수: {scores}")

✔ Numpy의 dot product 연산을 활용하여 매우 빠르게 유사한 데이터를 찾을 수 있습니다.
✔ 작은 규모의 데이터라면 벡터 데이터베이스 없이도 충분히 빠르게 검색이 가능합니다.


728x90

벡터 데이터베이스 없이도 최적의 임베딩 저장과 검색 가능!

  • CSV, Pickle, Numpy 등의 기존 방식은 효율적이지 않음
  • Parquet 파일 을 사용하면 공간 절약 + 빠른 데이터 로딩 가능
  • Polars 라이브러리 를 활용하면 데이터 검색 및 필터링 속도 향상
  • 작은 규모의 프로젝트에서는 벡터 데이터베이스 없이도 충분히 빠른 검색 가능

"벡터 데이터베이스를 꼭 사용해야 할까?"
👉 작은 프로젝트에서는 Parquet + Polars 조합이 더 효율적일 수도 있습니다!
https://minimaxir.com/2025/02/embeddings-parquet/

The Best Way to Use Text Embeddings Portably is With Parquet and Polars

Never store embeddings in a CSV!

minimaxir.com

728x90
반응형