Oracle Database 23ai 벡터 백엔드 운영 가이드
GenD 인제스트 파이프라인은 임베딩을 세 번째 벡터 백엔드인 Oracle Database 23ai
AI Vector Search 로 적재할 수 있다. 고객/벤더가 제공한 Oracle 인스턴스에 컬렉션
단위로 테이블을 만들고 VECTOR 컬럼 + 벡터 인덱스로 검색한다.
Oracle 23ai 에서 "벡터 DB" 는 별도 제품이 아니라 기능이다. 정형 데이터와 벡터가 같은 인스턴스에 공존하며, GenD 는 동일한 SQL/스키마로 양쪽을 다룬다.
아키텍처 요약
OracleVectorBackend가 기존VectorBackendABC 를 구현하고 팩토리get_vector_backend("oracle")로 해소된다.python-oracledbthin 모드 비동기 커넥션 풀을 사용한다 — Oracle Client 설치가 필요 없어 슬림/ARM64 컨테이너와 호환된다.- 컬렉션 1개당 테이블 1개를 만들고
VECTOR(<dim>, FLOAT32)컬럼 + IVF(기본) 또는 HNSW 벡터 인덱스를 생성한다. - Oracle 는 항상 외부(external) 엔드포인트다 — GenD 에 번들되지 않는다. dev 는 외부 23ai Free 컨테이너, prod 는 벤더 SaaS/매니지드.
- 임베딩은 GenD 측에서 생성한다(GenOS 임베딩 API). 적재 경로는 동기
IngestionService와 Dagsterupsert_vector자산 모두 팩토리를 통과하므로 오케스트레이션 코드 변경이 없다.
컬렉션별 Oracle 선택
특정 컬렉션을 Oracle 로 적재하려면 IngestionPolicy.vector_backend_type 를
"oracle" 로 설정한다. 벡터 인덱스 종류는 IngestionPolicy.oracle_index_type
(ivf | hnsw | none, 기본 ivf) 로 저장·노출된다.
Pipeline Studio 그래프에서는 builtin.vector 노드의 config.backend 를
"oracle" 로 지정하면 해당 노드만 Oracle 로 라우팅된다(미지정 시 런 기본
Weaviate 백엔드 사용).
백엔드 해소 실패는 원인에 따라 동작이 갈린다.
- 백엔드 미설정 (
config.backend미지정이고 런 기본 백엔드도 없는 환경, 또는 gend_api 팩토리 자체를 적재할 수 없는 CI/code-server) — 적재를 건너뛰고upserted=0으로 기록한다(graceful-skip). 이는 환경 조건이며 런을 실패시키지 않는다. - 백엔드 설정됨, 그러나 도달 불가 (예: Oracle 엔드포인트 다운) — upsert 시점에
예외가 전파되어 런이 실패한다(fail-loud). 다운된 싱크를
upserted=0으로 조용히 기록해 누락을 거짓 성공으로 숨기지 않는다. - 백엔드 이름 오타/미지원 (
config.backend가 명시됐지만 팩토리가 거부) — 사용자 오설정으로 보고 런을 즉시 실패시킨다(fail-loud).
필수 환경변수 / Secret
운영에서는 GEND_ORACLE_* 를 Secret 으로 주입한다(기본값 없음).
| 환경변수 | 의미 | 비고 |
|---|---|---|
GEND_ORACLE_DSN | Easy Connect host:port/service_name 또는 wallet alias | RAC 는 SID 아님, service_name |
GEND_ORACLE_USER | 전용 스키마 계정 | |
GEND_ORACLE_PASSWORD | 계정 비밀번호 | vault_enabled 시 Vault 암호화 |
GEND_ORACLE_WALLET_DIR | TLS/mTLS wallet 디렉터리(ADB) | 비우면 평문 TCP |
GEND_ORACLE_INDEX_TYPE | 기본 벡터 인덱스(ivf/hnsw/none) | 기본 ivf |
GEND_ORACLE_POOL_MIN | 비동기 풀 최소 연결 | 기본 1 |
GEND_ORACLE_POOL_MAX | 비동기 풀 최대 연결 | 기본 4, ADB Always Free 는 보수적으로 |
임베딩을 GenOS 서빙으로 보내려면:
| 환경변수 | 의미 |
|---|---|
GEND_AI_EMBEDDING_PROVIDER=genos | OpenAI 호환 GenOS 임베딩 사용 |
GEND_GENOS_EMBEDDING_URL | 예: https://genos.example/v1 |
GEND_GENOS_EMBEDDING_TOKEN | GenOS 토큰 |
GEND_EMBEDDING_DIMENSIONS | VECTOR(<dim>) 고정 차원(기본 1536) |
GEND_EMBEDDING_DIMENSIONS 는 Oracle VECTOR(<dim>) 컬럼 폭을 결정한다.
임베딩 모델 차원과 다르면 업서트가 차원 불일치로 스킵된다 — 모델 차원과 반드시
일치시킬 것.
벡터 인덱스 종류 (D5)
- IVF (기본) — 모든 RU 에서 동작하고 DML 친화적이며 자동 재구성된다.
컬렉션 생성 시
ORGANIZATION NEIGHBOR PARTITIONS ... DISTANCE COSINE. - HNSW —
ORGANIZATION INMEMORY NEIGHBOR GRAPH. 트랜잭션 일관 DML 은 RU ≥ 23.6 에 의존하며 SGAVECTOR_MEMORY_SIZE풀(DBA 설정)이 필요하다. 현재 단계에서는 옵션화/Deferred. - none — 인덱스를 만들지 않는다(소규모/실험).
헬스 모니터링
GET /api/v1/ingestion/stores/health 는 구성된 각 벡터 백엔드의 도달 가능성을
반환한다. Oracle 의 reachable 은 외부 엔드포인트에 대한 실시간
SELECT 1 FROM dual 결과다. 한 백엔드가 불통이어도 나머지를 가리지 않는다.
{
"weaviate": {"reachable": true},
"milvus": {"reachable": false},
"oracle": {"reachable": true}
}
벤더 산출물 체크리스트 (staging/prod)
"VDB 접속 계정" 만으로는 부족하다. 아래를 벤더에게 요청한다:
- 23ai 인스턴스 —
COMPATIBLE ≥ 23.4, RU 버전 명시(IVF 는 23.4+, 추후 HNSW 면 23.6+), 캐릭터셋 AL32UTF8(한글). - 전용 스키마 계정 + 권한:
CREATE SESSION,CREATE TABLE,CREATE INDEX(+CREATE VECTOR INDEX), 테이블스페이스 quota. - (HNSW 사용 시) SGA
VECTOR_MEMORY_SIZE풀 설정 — DBA 만 가능. - 접속: host / port / service_name(RAC 면 SID 아님) (+TLS 면 wallet zip 과 비밀번호).
- 네트워크 allowlist: GenD AKS egress → Oracle listener 포트.
- dev/test 인스턴스 분리 (또는 23ai Free 로 대체).
- 예상 벡터 건수 기준 테이블스페이스 용량 협의.
- (GenOS 측) 임베딩 모델 차원값 —
VECTOR(<dim>)고정용. - 벡터 적재 대상이 정형 데이터와 같은 인스턴스인지 벡터 전용 인스턴스인지 — DSN/용량/네트워크 결정용(코드 불변).
dev/prod 패리티
| 항목 | dev | prod |
|---|---|---|
| 인스턴스 | 외부 23ai Free 컨테이너 | 벤더 SaaS/매니지드(ADB / Database@Azure / Base DB) |
| 접속 | 평문 TCP user/pass | TLS/mTLS(wallet) |
| 코드 | 동일 OracleVectorBackend/스키마/벡터 SQL | 동일 |
게이트된 통합 테스트 실행
apps/api/tests/test_oracle_backend_integration.py 는 실제 23ai 인스턴스 대상
종단 라운드트립 테스트다. GEND_ORACLE_DSN 이 없으면 자동 스킵되며, 일반 CI 에서는
실행되지 않는다.
외부 23ai Free 컨테이너를 띄운다:
docker run -d --name oracle-free -p 1521:1521 \
-e ORACLE_PASSWORD=GendTest123 \
gvenzl/oracle-free:23-slim
전용 앱 계정(CREATE SESSION/TABLE/INDEX + quota)을 만든 뒤 실행한다:
cd apps/api
GEND_ORACLE_DSN=localhost:1521/FREEPDB1 \
GEND_ORACLE_USER=gend GEND_ORACLE_PASSWORD=GendTest123 \
PYTHONPATH=src .venv/bin/python -m pytest \
tests/test_oracle_backend_integration.py -v
테스트는 ensure_collection → 멱등 MERGE 업서트(차원=embedding_dimensions) →
JSON_VALUE(metadata, '$.dept') 라운드트립 → VECTOR_DISTANCE 최근접이
결정적 object_id 인지 확인 → delete_by_document_id → health_check → 테이블 DROP
정리까지 검증한다.
컬렉션 이름은 _safe_identifier 가 대문자로 변환한다. 컬렉션 zz_gend_it_xxxx
는 테이블 ZZ_GEND_IT_XXXX 가 되므로 원시 SQL 은 대문자 이름으로 조회한다.