PostgreSQL pgvector 사용 가이드

PostgreSQL pgvector 사용 가이드

개요

이 문서에서는 Samsung Cloud Platform PostgreSQL(DBaaS), EPAS(DBaaS) 상품에서 pgvector extension 을 사용하기 위한 방법에 대해 다뤄 보겠습니다. PostgreSQL 에서는 extension 기능을 통해 PostgreSQL 에서 제공하지 않는 추가적인 기능을 사용할 수 있습니다. pgvector extension 은 PostgreSQL 에 오픈소스 벡터 유사성 검색을 추가합니다. 이 문서에서는 pgvector extension 을 사용하도록 설정하는 방법과 벡터를 만들고 저장하고 쿼리하는 방법에 대해 알아봅니다. 현재 최신 버전은 v0.8.0 이며, 보다 상세한 사용 방법은 공식 문서(https://github.com/pgvector/pgvector/blob/master/README.md) 에서 확인 가능합니다.

개념

벡터 유사성(Vector similarity)

벡터 유사성은 두 항목을 일련의 숫자인 벡터로 표시하여 두 항목이 얼마나 비슷한지 측정하는 데 사용하는 방법입니다. 벡터 유사성은 일반적으로 코사인 유사도(cosine similarity) 또는 유클리드 거리(Euclidean distance) 같은 거리 메트릭을 사용하여 계산됩니다. 유클리드 거리는 두 벡터 간의 직선 거리를 측정하는 반면, 코사인 유사도는 두 벡터간 각도의 코사인값을 측정합니다. 유사도 값은 일반적으로 0 과 1 사이의 값을 가지며 높은 값일수록 유사도가 높습니다. 벡터 유사성은 권장 시스템, 텍스트 분류, 이미지 인식 및 클러스터링 같은 다양한 어플리케이션에서 널리 사용됩니다.

임베딩(Embedding)

임베딩은 텍스트, 이미지, 비디오 또는 기타 유형 정보의 관련성을 평가하는 기술입니다. 평가를 통해 기계 학습 모델이 데이터 간의 관계와 유사성을 효율적으로 식별할 수 있게 하여 패턴을 인식하고 정확한 예측을 하게 합니다.

pgvector extension 사용하기

pgvector extension 사용가능 여부 확인

pgvector extension 이 설치되어 있어 사용 가능한지 여부를 먼저 확인합니다.

SELECT * FROM pg_catalog.pg_available_extensions where name=pgvector;

만약 목록에 표시되지 않는다면 해당 DB 서버에 pgvector extension 패키지 설치가 되어 있지 않은 것이므로 Samsung Cloud Platform Conolse의 ‘1:1 문의’를 통해 패키지 설치 요청 후 진행하시기 바랍니다.

pgvector extension 활성화

pgvector extension 을 활성화하기 위해 CREATE EXTENSION 구문을 실행하여 패키지를 DB 에 로드합니다.

CREATE EXTENSION pgvector;

pgvector extension 사용 방법

데이터 저장

  • vector 타입의 컬럼을 가진 테이블 생성

    CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));
    
  • 기존 테이블에 vector 타입의 컬럼 추가

    ALTER TABLE items ADD COLUMN embedding vector(3);
    
  • vector 데이터 Insert

    INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]');
    
  • vector 데이터 Upsert

    INSERT INTO items (id, embedding) VALUES (1, '[1,2,3]'), (2, '[4,5,6]') ON CONFLICT (id) DO UPDATE SET embedding = EXCLUDED.embedding;
    
  • vector 데이터 Update

    UPDATE items SET embedding = '[1,2,3]' WHERE id = 1;
    
  • vector 데이터 Delete

    DELETE FROM items WHERE id = 1;
    

데이터 조회

  • 특정 vector 값에 대한 Nearest neighbor 검색 (유클리드 거리)

    SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
    
  • 특정 row 에 대한 Nearest neighbor 검색 (유클리드 거리)

    SELECT * FROM items WHERE id != 1 ORDER BY embedding <-> (SELECT embedding FROM items WHERE id = 1) LIMIT 5;
    
  • 특정 vector 값에 대해 특정 거리 이내의 row 조회 (유클리드 거리)

    SELECT * FROM items WHERE embedding <-> '[3,1,2]' < 5;
    

pgvector 에서는 유사성 계산에 사용할 수 있는 3 개의 연산자를 제공합니다.

연산자설명
<->유클리드 거리
<#>음의 내적
<=>코사인 거리
표. pgvector 제공 연산자

  • 유클리드 거리 조회

    SELECT embedding <-> '[3,1,2]' AS distance FROM items;
    
  • 내적 조회(내적은 음의 값을 반환하기 때문에 -1 을 곱하기)

    SELECT (embedding <#> '[3,1,2]') * -1 AS inner_product FROM items;
    
  • 코사인 유사성 조회(1 – 코사인 거리 사용)

    SELECT 1 - (embedding <=> '[3,1,2]') AS cosine_similarity FROM items;
    
  • vector 평균 조회

    SELECT AVG(embedding) FROM items;
    
  • vector 그룹 평균 조회

    SELECT category_id, AVG(embedding) FROM items GROUP BY category_id;
    

데이터 인덱싱

성능을 위해 Approximate nearest neighbor 검색을 사용하기 위해 인덱스를 추가할 수 있습니다. 일반적인 인덱스와 달리 인덱스 추가 후에 검색 결과가 달라질 수 있습니다. 단, 최대 2,000 차원의 벡터까지 인덱싱할 수 있습니다.

  • L2 거리 인덱스 생성

    CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100);
    
  • 내적 인덱스 생성

    CREATE INDEX ON items USING ivfflat (embedding vector_ip_ops) WITH (lists = 100);
    
  • 코사인 거리 인덱스 생성

    CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
    

데이터 필터링

WHERE 절에 사용되는 조건 검색 컬럼에 대한 인덱스를 생성하여 활용할 수 있습니다.

  • 조건 검색 컬럼 인덱스 생성

    CREATE INDEX ON items (category_id);
    
  • 조건 검색 컬럼 활용 조회

    SELECT * FROM items WHERE category_id = 123 ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
    
  • 부분 인덱스 생성(https://www.postgresql.org/docs/current/indexes-partial.html)

    CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100) WHERE (category_id = 123);
    

파티셔닝을 활용하여 데이터셋을 나눌 수도 있습니다.(https://www.postgresql.org/docs/current/ddl-partitioning.html)

  • 파티션 테이블 생성(LIST 파티션)

    CREATE TABLE items (embedding vector(3), category_id int) PARTITION BY LIST(category_id);
    

하이브리드 검색

PostgreSQL 의 full-text 검색과 함께 사용하여 하이브리드 검색을 할 수 있습니다.(https://www.postgresql.org/docs/current/textsearch-intro.html)

SELECT id, content FROM items, plainto_tsquery('hello search') query WHERE textsearch @@ query ORDER BY ts_rank_cd(textsearch, query) DESC LIMIT 5;