객체 집합 질의의 실행 경로와 한도
객체 집합 서비스(Object Set Service, OSS)는 온톨로지의 객체(Object)를 질의하고 반환합니다. 질의의 복잡도, 대상 규모와 가용 자원에 따라 저장 계층, 메모리 또는 Spark 분산 실행을 선택합니다. 한 복잡한 질의의 서로 다른 단계에서 여러 방식을 함께 사용할 수 있습니다.
실행 방식
| 방식 | 적용 상황 | 성능과 연산 비용 |
|---|---|---|
| 저장 계층으로 밀어내기(Pushdown) | 인덱스로 해결할 수 있는 기본 필터와 집계 | 가장 빠르고 연산 부담이 작습니다. |
| 메모리 실행 | 더 복잡한 연산이지만 메모리 용량 안에 들어오는 규모 | 비교적 빠르며 중간 수준의 연산을 사용합니다. |
| Spark 분산 실행 | 메모리 실행 규모를 넘는 Search Around 및 파생 속성 등의 연산 | 더 큰 집합을 처리하지만 지연과 컴퓨팅 사용량이 증가합니다. |
Object Storage V2의 기본 임계값
| 항목 | 기준 |
|---|---|
| 메모리에서 Spark로 전환 | Search Around와 파생 속성에서 기본 100,000개 객체 |
| 내부 데이터 로딩 페이지 | 어느 로딩 단계라도 25페이지를 넘으면 Spark로 전환 |
| Search Around 한 번의 결과 집합 | 단일 데이터소스에서 읽는 결과인 leaf에 최대 10,000,000개 객체 |
| 질의 실행 중 모든 데이터셋의 로딩 합계 | 최대 30,000,000개 객체 |
기본 비교에서는 100,000개 이하를 메모리에서 처리하고 이를 넘는 복잡한 탐색을 Spark로 처리합니다. 단순 인덱스 조회와 단계별 최적화도 함께 고려하므로 전체 데이터 크기 하나만으로 모든 실행 방식을 판단하지 않습니다.
OSS는 크기를 추정하여 실행 가능 여부를 판단합니다. 추정 크기가 적용 한도의 두 배보다 크게 나타나면 정확한 개수를 끝까지 세기 전에 질의가 실패할 수 있습니다.
호출 API의 메모리 한도
TypeScript v1 Functions on Objects의 all()과 allAsync()는 최대 100,000개 객체를 메모리에 올립니다. 함수 로직에 따라 10,000개를 넘는 로드만으로도 실행 시간이 초과될 수 있습니다. 두 숫자는 각각 개수 상한과 시간 초과 위험의 기준입니다.
이 메서드를 사용하는 TypeScript v1 검색은 Search Around 깊이도 최대 3회입니다. 이는 Ontology SDK에서 정의하는 모든 종류의 링크 탐색에 동일하게 적용하는 일반 한도가 아닙니다.
TypeScript OSDK 2.x에는 all()과 allAsync()가 없습니다. fetchPage나 asyncIter로 페이지를 읽습니다. getAllObjects 계열 API의 대규모 로드와 이런 페이지 조회는 클라이언트에서 한 번에 전체 배열을 만드는 방식과 구분합니다.
KNN 검색은 별도 조건을 따릅니다. TypeScript v1에서는 Object Storage V2만 지원하고 K는 1부터 100까지입니다. 질의 벡터는 인덱스 벡터와 길이가 같아야 하며 최대 2048차원입니다. 이 범위를 넘으면 오류가 발생합니다.
페이지 길이와 종료 판단
메모리 제한 때문에 한 페이지에 요청한 개수보다 적은 객체가 돌아와도 다음 결과가 남아 있을 수 있습니다. 페이지 길이로 마지막 페이지를 판단하지 않고 반환된 다음 페이지 토큰이 없어질 때까지 계속 읽습니다.
구형 loadObjects는 요청한 객체 전체를 반환해야 하므로 일부 결과만 돌려줄 수 없습니다. 메모리 한도를 넘으면 ObjectSet:ResultSizeLimitExceeded 오류를 반환합니다. 이 엔드포인트를 사용하는 호출은 StaticObjectSetV2 기반의 페이지 엔드포인트로 옮깁니다.
Search Around의 결과 집합
고객 집합에서 연결된 주문을 찾는다면 시작 집합은 고객이고 결과 집합은 주문입니다. OSS는 결과 쪽 객체 중 연결 조건이 맞는 객체를 남기는 왼쪽 세미 조인(Left-semi join)을 사용합니다. 시작 객체의 자료를 붙여 행을 복제하지 않습니다.
10,000,000개 한도는 이 탐색으로 반환하는 서로 다른 주문 객체의 집합에 적용합니다. 출발 고객 수와 결과 주문 수를 구분하여 예상 규모를 계산합니다.
질의 구성
기본 속성의 필터를 조인과 객체 로드 전에 적용합니다. 계산한 SQL 열이나 파생 값의 조건은 후보 행을 계산해야 할 수 있어 작은 집합에서도 메모리 또는 Spark 단계가 필요할 수 있습니다. 다만 파생 속성의 Collect list와 Collect set은 원본 인덱스로 검색을 밀어낼 수 있으므로 모든 파생 속성에 대해 인덱스를 사용할 수 없다고 단정하지 않습니다.
예를 들어 date형 order_date에서 2026년 5월 자료를 찾을 때에는 월과 연도를 각각 계산하여 비교하기보다 order_date >= '2026-05-01' AND order_date < '2026-06-01'처럼 범위를 지정합니다. 시작일을 포함하고 다음 달 시작일을 제외합니다. 실제 API에서는 그 API의 범위 및 논리 결합 연산자를 사용합니다.
큰 집합은 페이지 단위로 처리하고 비싼 탐색 전에 집계로 규모를 파악합니다. 자주 한도에 닿는다면 더 좁은 업무용 유형과 링크를 구성하거나 비정규화와 갱신 책임을 검토합니다. Spark 대체 실행에는 추가 컴퓨팅 사용량이 발생합니다.
구형 Object Storage V1 참고
Object Storage V1(Phonograph)의 지정된 지원 종료일은 2026년 6월 30일입니다. 남아 있는 V1 리소스는 OSv2 이전 절차를 확인합니다. 구형 리소스와 과거 실행을 해석할 때에는 다음 차이를 구분합니다.
- all()과 allAsync()의 메모리 로드는 최대 100,000개였습니다.
- Search Around의 결과 집합도 최대 100,000개였습니다.
- 더 큰 질의를 Spark로 자동 전환하는 경로가 없었습니다.
새 구성은 V2를 사용합니다. 구형 리소스의 이전은 객체 유형과 조인 테이블을 사용하는 다대다 링크 유형을 함께 검토합니다.