SQL 및 PPL 제한 사항

SQL 및 PPL 제한 사항

SQL 플러그인에는 다음과 같은 제한 사항이 있어요. 쿼리를 설계할 때 이 제한 사항을 염두에 두면 OpenSearch에서 최적의 동작으로 쿼리를 만들 수 있어요.

출처: 문서

본문

표현식에 대한 집계는 지원되지 않아요(Aggregation over expression is not supported)

집계는 필드에만 적용할 수 있어요. 집계는 표현식을 매개변수로 받을 수 없어요. 예를 들어 avg(log(age))는 지원되지 않아요.

FROM 절의 하위 쿼리(Subquery in the FROM clause)

SELECT outer FROM (SELECT inner) 형식의 FROM 절 하위 쿼리는 쿼리가 하나의 쿼리로 병합될 때만 지원돼요. 예를 들어 다음 쿼리는 지원돼요.

SELECT t.f, t.d
FROM (
    SELECT FlightNum as f, DestCountry as d
    FROM opensearch_dashboards_sample_data_flights
    WHERE OriginCountry = 'US') t

하지만 외부 쿼리에 GROUP BY나 ORDER BY가 있으면 지원되지 않아요.

JOIN 쿼리

OpenSearch는 관계형 연산을 기본적으로 지원하지 않으므로 JOIN 쿼리는 최선 노력(best-effort) 방식으로 지원돼요.

JOIN은 조인된 결과에 대한 집계를 지원하지 않아요

JOIN 쿼리는 조인된 결과에 대한 집계를 지원하지 않아요.

예를 들어 SELECT depo.name, avg(empo.age) FROM empo JOIN depo WHERE empo.id = depo.id GROUP BY depo.name은 지원되지 않아요.

성능(Performance)

JOIN 쿼리는 비용이 많이 드는 인덱스 스캔 연산이 발생하기 쉬워요.

JOIN 쿼리는 5백만 개가 넘는 일치 레코드가 있는 결과 집합을 다룰 때 성능 문제가 발생할 수 있어요. JOIN 성능을 개선하려면 먼저 데이터를 필터링하여 조인되는 레코드 수를 줄여요. 예를 들어 키 값의 특정 범위로 조인을 제한해요.

SELECT l.key, l.spanId, r.spanId
  FROM logs_left AS l
  JOIN logs_right AS r
  ON l.key = r.key
  WHERE l.key >= 17491637400000
    AND l.key < 17491637500000
    AND r.key >= 17491637400000
    AND r.key < 17491637500000
  LIMIT 10

기본적으로 JOIN 쿼리는 과도한 리소스 소비를 방지하기 위해 60초 후 자동으로 종료돼요. 쿼리에서 힌트를 사용해 이 제한 시간을 조정할 수 있어요. 예를 들어 5분(300초) 제한 시간을 설정하려면 다음 코드를 사용해요.

SELECT /*! JOIN_TIME_OUT(300) */ left.a, right.b FROM left JOIN right ON left.id = right.id;

이 성능 제한 사항은 외부 데이터 소스 쿼리에는 적용되지 않아요.

페이지네이션은 기본 쿼리만 지원해요(Pagination only supports basic queries)

페이지네이션 쿼리를 사용하면 페이지네이션된 응답을 받을 수 있어요.

현재 페이지네이션은 기본 쿼리만 지원해요. 예를 들어 다음 쿼리는 커서 ID로 데이터를 반환해요.

POST _plugins/_sql/
{
  "fetch_size" : 5,
  "query" : "SELECT OriginCountry, DestCountry FROM opensearch_dashboards_sample_data_flights ORDER BY OriginCountry ASC"
}

커서 ID가 있는 JDBC 형식의 응답이에요.

{
  "schema": [
    {
      "name": "OriginCountry",
      "type": "keyword"
    },
    {
      "name": "DestCountry",
      "type": "keyword"
    }
  ],
  "cursor": "d:eyJhIj...NTh9",
  "total": 13059,
  "datarows": [[
    "AE",
    "CN"
  ]],
  "size": 1,
  "status": 200
}

aggregation과 join이 있는 쿼리는 현재 페이지네이션을 지원하지 않아요.

쿼리 처리 엔진(Query processing engines)

OpenSearch 3.0.0 이전에 SQL 플러그인은 V1과 V2 두 가지 쿼리 처리 엔진을 사용했어요. 두 엔진 모두 대부분의 기능을 지원했지만 V2만 활발히 개발 중이었어요. 쿼리를 실행하면 플러그인은 먼저 V2 엔진으로 실행을 시도하고, 실패하면 V1으로 폴백했어요. V2에는 지원되지만 V1에는 없는 쿼리는 실패하고 오류 응답을 반환했어요.

OpenSearch 3.0.0부터 SQL 플러그인은 쿼리 최적화와 실행에 Apache Calcite를 활용하는 새 쿼리 엔진(V3)을 도입했어요. V3는 OpenSearch 3.0.0의 실험적 기능이므로 기본적으로 비활성화되어 있어요. 이 새 엔진을 활성화하려면 plugins.calcite.enabled를 true로 설정해요. V2에서 V1으로 폴백하는 로직과 유사하게, 쿼리를 실행하면 플러그인은 먼저 V3 엔진으로 실행을 시도하고 실패하면 V2로 폴백해요. V3에 대한 자세한 내용은 PPL Engine V3을 참조해요.

V1 엔진 제한 사항

V1 쿼리 엔진은 OpenSearch의 원래 SQL 처리 엔진이에요. 대부분 새 엔진으로 대체되었지만, 그 제한 사항을 이해하면 특히 쿼리가 V2에서 V1으로 폴백될 때 특정 쿼리 동작을 설명하는 데 도움이 돼요. 다음 제한 사항은 V1 엔진에만 적용돼요.

  • FROM 절이 없는 리터럴 표현식 선택은 지원되지 않아요. 예를 들어 SELECT 1은 지원되지 않아요.
  • WHERE 절은 표현식을 지원하지 않아요. 예를 들어 SELECT FlightNum FROM opensearch_dashboards_sample_data_flights where (AvgTicketPrice + 100) <= 1000은 지원되지 않아요.
  • 대부분의 관련성 검색 함수는 V2 엔진에서만 구현돼요.

이런 쿼리는 V1 전용 함수가 없는 한 V2 엔진에서 성공적으로 실행돼요. 이런 제한 사항을 만날 일은 거의 없어요.

V2 엔진 제한 사항

V2 쿼리 엔진은 대부분의 최신 SQL 쿼리 패턴을 처리해요. 하지만 복잡한 분석 워크로드에서 특히 쿼리 개발에 영향을 줄 수 있는 특정 제한 사항이 있어요. 이 제한 사항을 이해하면 OpenSearch에서 최적으로 동작하는 쿼리를 설계하는 데 도움이 돼요.

  • 커서 기능은 V1 엔진에서만 지원돼요. V2 엔진에서 cursor/pagination 지원은 GitHub issue #656을 추적해요.
  • json 형식 출력은 V1 엔진에서만 지원돼요.
  • V2 엔진은 쿼리 실행 시간을 추적하지 않으므로 느린 쿼리가 보고되지 않아요.
  • V2 쿼리 엔진은 OpenSearch 엔진에서 쿼리를 실행할 뿐만 아니라 복잡한 쿼리에 대한 후처리도 지원해요. 따라서 explain 출력은 더 이상 OpenSearch 도메인 특화 언어(DSL)가 아니라 V2 쿼리 엔진의 쿼리 계획 정보도 포함해요.
  • V2 쿼리 엔진은 histogram, date_histogram, percentiles, topHits, stats, extended_stats, terms, range 같은 집계 쿼리를 지원하지 않아요.
  • JOIN과 하위 쿼리는 지원되지 않아요. JOIN과 하위 쿼리의 개발 진행 상황을 보려면 GitHub issue #1441과 GitHub issue #892를 추적해요.
  • OpenSearch는 배열 데이터 타입을 기본적으로 지원하지 않지만 다중 값 필드를 암시적으로 허용해요. SQL/PPL 플러그인은 인덱스 매핑에 정의된 데이터 타입 의미론을 엄격히 준수해요. OpenSearch 응답을 파싱할 때 데이터가 선언된 타입과 일치할 것으로 기대하며 배열의 모든 데이터를 해석하지 않아요. plugins.query.field_type_tolerance 설정이 활성화되면 SQL/PPL 플러그인은 스칼라 데이터 타입을 반환하여 배열 데이터 세트를 처리하며 기본 쿼리(예: SELECT * FROM tbl WHERE condition)를 허용해요. 그러나 표현식이나 함수에서 다중 값 필드를 사용하면 예외가 발생해요. 이 설정이 비활성화되거나 설정되지 않으면 배열의 첫 번째 요소만 반환되어 기본 동작을 유지해요.
  • nested 쿼리에 대한 PartiQL 구문은 지원되지 않아요.

V3 엔진 제한 사항 및 제약

V3 쿼리 엔진은 Apache Calcite를 사용해 향상된 쿼리 처리 기능을 제공해요. OpenSearch 3.0.0의 실험적 기능으로, 쿼리를 개발할 때 알아야 할 특정 제한 사항과 동작 차이가 있어요. 이 제한 사항은 새 제약, 지원되지 않는 기능, 동작 변경의 세 가지 범주로 나뉘어요.

제약(Restrictions)

V3 엔진은 OpenSearch 메타데이터 필드에 대해 더 엄격한 검증을 적용해요. 필드 이름을 조작하는 명령을 사용할 때 다음 제약 사항을 알아두세요.

지원되지 않는 기능(Unsupported functionalities)

V3 엔진은 이전 엔진에서 사용 가능한 모든 기능을 지원하지 않아요. 다음 기능에 대해서는 쿼리가 자동으로 V2 쿼리 엔진으로 전달돼요.

  • trendline
  • show datasource
  • describe
  • top and rare
  • fillnull
  • patterns
  • consecutive=true가 있는 dedup
  • 검색 관련 명령: AD, ML, Kmeans
  • fetch_size 매개변수가 있는 명령
  • _id 또는 _doc 같은 메타데이터 필드가 있는 쿼리
  • JSON 관련 함수: cast to json, json, json_valid
  • 검색 관련 함수: match, match_phrase, match_bool_prefix, match_phrase_prefix, simple_query_string, query_string, multi_match
V2와 V3 비교

V3 엔진은 내부적으로 다른 구현을 사용하므로 일부 동작이 이전 버전과 달라졌어요. V3의 동작이 올바른 것으로 간주되지만 V2의 동일한 쿼리와 다른 결과를 만들 수 있어요. 다음 표는 이러한 차이를 보여줘요.

Item V2 V3
timestampdiff의 반환 타입 timestamp int
regexp의 반환 타입 int boolean
count, dc, distinct_count의 반환 타입 int bigint
ceiling, floor, sign의 반환 타입 int 입력과 동일한 타입
값 “Amber JOHnny”에 대한 like(firstname, 'Ambe_') true false
값 “Amber JOHnny”에 대한 like(firstname, 'Ambe*') true false
cast(firstname as boolean) false null
pushdown이 활성화된 상태에서 여러 null 값의 합 0 null
percentile(null, 50) 0 null

더 알아보기 (Learn more)