본문 바로가기

개발/Others

[ELK] 마치 SQL처럼 사용하자

ElasticSearch와 OpenSearch에서는 데이터의 조회를 마치 RDB의 SQL처럼 사용할 수 있는 기능들을 제공하고 있다.

 

ElasticSearch

POST /_sql
{
	"query": "select item from {index}* where item = {item_name}"
}
// 와일드카드(*)를 사용해 해당 이름을 가진 모든 인덱스를 대상으로 조회가 가능하다.

OpenSearch

POST /_plugins/_sql
{
	"query": "select item from {index}* where item = {item_name}"
}

where 뿐만 아니라 group by, having 등 더 다양한 기능들을 지원하고 있다.

파라미터 바인딩도 지원한다

POST /_plugins/_sql
{
	"query": "select item from {index}* where item = ? ",
    "parameters": 
    [
    	"type": "string",
        "value": "{item_name}"
    ]
}

※ 보통 외부 요청에서 조회시에  파라미터 바인딩을 하지 않고, where 조건에 직접 변수를 입력하는 방식으로 주기적으로      요청을 보내게 되면, 동적 쿼리 컴파일 제한에 걸리게 된다. (OpenSearch 기준) 75/5m 을 기본 값으로 가지고 있으며,

    5분에 75회 동적 쿼리 컴파일에 도달하게 되면, 조회에 제한이 걸린다.

Caused by: org.opensearch.common.breaker.CircuitBreakingException: [script] Too many dynamic script compilations within, max: [75/5m]; please use indexed, or scripts with parameters instead; this limit can be changed by the [script.context.filter.max_compilations_rate] setting

위와 같은 메시지를 1분 이내에 만나게 될지도..

 

동적 쿼리 제한에 대한 설정은 아래와 같이 변경할 수 있다.

PUT localhost:9200/_cluster/settings
{
    "transient": {
        "script.max_compilations_rate": "1000/1m"
    }
}

하지만 가장 좋은 방법은 동적 쿼리 자체가 생성되지 않도록 하는 방법이다. 컴파일 자체가 OpenSearch의 자원사용량을 늘리는 지름길이기 때문..

끝없이 늘어나는 컴파일과 캐시..

결론은 앞서 설명한 "파라미터 바인딩을 사용하자"가 되겠다.


기존의 RDB 구조에서 OpenSearch로 전환하는 과정에 있어, 기존 데이터에 group by 조건이 많다면 sql 형식으로 조회해보는 방법도 괜찮은 것으로 보인다. OpenSearch의 QueryDSL 방식으로 조회할 때, aggregate의 대상이 늘어날 수록 json의 depth가 너무 깊어졌기 때문인데, 더 좋은 방법들이 있을 수 있으니 이 글을 읽게 된다면 이 방법들이 정답이라기보다는 조회하는 과정이나, 설정의 변경 정도만 참고하면 좋을 것 같다.

 

또한 공식문서를 보면 훨씬 더 다양한 사용방법들을 제시해주고 있다.

https://opensearch.org/docs/latest/search-plugins/sql/sql-ppl-api/

 

SQL/PPL API

SQL/PPL API

opensearch.org