Profile API
Profile API
Profile API는 검색 요청의 개별 구성 요소 실행에 대한 타이밍 정보를 제공해요. Profile API를 사용해 느린 요청을 디버깅하고 성능을 개선하는 방법을 이해할 수 있어요. Profile API는 다음 항목은 측정하지 않아요:
- 네트워크 지연 시간
- 요청이 큐에서 보내는 시간
- 코디네이팅 노드에서 샤드 응답을 병합하는 동안의 유휴 시간
Profile API는 리소스를 많이 소모하는 작업으로, 검색 작업에 오버헤드를 추가해요.
도입 버전 1.0
엔드포인트
GET /testindex/_search
{
"profile": true,
"query" : {
"match" : { "title" : "wind" }
}
}
동시 세그먼트 검색
OpenSearch 2.12부터 concurrent segment search는 쿼리 단계에서 각 샤드 수준 요청이 세그먼트를 병렬로 검색할 수 있게 해줘요. Profile API 응답에는 *슬라이스(slice)*에 대한 통계를 담은 추가 필드가 몇 개 있어요.
슬라이스는 스레드가 실행할 수 있는 작업 단위예요. 각 쿼리는 여러 슬라이스로 분할될 수 있으며, 각 슬라이스는 하나 이상의 세그먼트를 포함해요. 모든 슬라이스는 풀에서 사용 가능한 스레드에 따라 병렬로 또는 어떤 순서로 실행될 수 있어요.
일반적으로 max/min/avg 슬라이스 시간은 특정 타이밍 유형에 대해 모든 슬라이스의 통계를 캡처해요. 예를 들어 집계를 프로파일링할 때 aggregations 섹션의 max_slice_time_in_nanos 필드는 모든 슬라이스에서 집계 작업과 그 자식들이 소비한 최대 시간을 보여줘요.
예제 요청: 비동시 검색
Profile API를 사용하려면 _search 엔드포인트로 보내는 검색 요청에 profile 파라미터를 true로 포함하세요:
GET /testindex/_search
{
"profile": true,
"query": {
"match": {
"title": "wind"
}
}
}
사람이 읽을 수 있는 형식을 켜려면 요청에 ?human=true 쿼리 파라미터를 포함하세요:
GET /testindex/_search?human=true
{
"profile": true,
"query": {
"match": {
"title": "wind"
}
}
}
응답에는 사람이 읽을 수 있는 단위를 가진 추가 time 필드가 포함돼요. 예를 들면:
"collector": [
{
"name": "SimpleTopScoreDocCollector",
"reason": "search_top_hits",
"time": "113.7micros",
"time_in_nanos": 113711
}
]
Profile API 응답은 장황하므로
curl명령으로 요청을 실행한다면?pretty쿼리 파라미터를 포함해 응답을 더 읽기 쉽게 만드세요.
예제 요청: 집계
집계를 프로파일링하려면 집계 요청을 보내고 profile 파라미터를 true로 제공하세요.
전역 집계
GET /opensearch_dashboards_sample_data_ecommerce/_search
{
"profile": "true",
"size": 0,
"query": {
"match": {
"manufacturer": "Elitelligence"
}
},
"aggs": {
"all_products": {
"global": {},
"aggs": {
"avg_price": {
"avg": {
"field": "taxful_total_price"
}
}
}
},
"elitelligence_products": {
"avg": {
"field": "taxful_total_price"
}
}
}
}
비전역 집계
GET /opensearch_dashboards_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"avg_taxful_total_price": {
"avg": {
"field": "taxful_total_price"
}
}
}
}
예제 응답: 비동시 검색
응답에는 프로파일링 정보가 포함돼요:
동시 세그먼트 검색
다음은 세 개의 세그먼트 슬라이스가 있는 동시 세그먼트 검색의 예제 응답이에요.
응답 본문 필드
응답에는 다음 필드가 포함돼요.
| 필드 | 데이터 타입 | 설명 |
|---|---|---|
| profile | Object | 프로파일링 정보를 담고 있어요. |
| profile.shards | 객체 배열 | 검색 요청은 인덱스의 하나 이상의 샤드에 대해 실행될 수 있고, 검색은 하나 이상의 인덱스와 관련될 수 있어요. 따라서 profile.shards 배열에는 검색에 참여한 각 샤드에 대한 프로파일링 정보가 포함돼요. |
| profile.shards.id | String | [node-ID][index-name][shard-ID] 형식의 샤드 ID예요. |
| profile.shards.searches | 객체 배열 | 검색은 기본 Lucene 인덱스에 대해 실행되는 쿼리를 나타내요. 대부분의 검색 요청은 Lucene 인덱스에 대해 단일 검색을 실행하지만, 일부 검색 요청은 둘 이상의 검색을 실행할 수 있어요. 예를 들어 전역 집계를 포함하면 전역 컨텍스트에 대한 보조 match_all 쿼리가 발생해요. profile.shards 배열에는 각 검색 실행에 대한 프로파일링 정보가 포함돼요. |
| profile.shards.searches.query | 객체 배열 | 쿼리 실행에 대한 프로파일링 정보예요. |
| profile.shards.searches.rewrite_time | Integer | 모든 Lucene 쿼리는 다시 작성(rewrite)돼요. 쿼리와 그 자식은 쿼리가 더 이상 변하지 않을 때까지 여러 번 다시 작성될 수 있어요. 다시 작성 과정에는 중복 절 제거, 비효율적인 쿼리 경로를 더 효율적인 경로로 교체 같은 최적화 수행이 포함돼요. 다시 작성 과정 후 원래 쿼리는 크게 달라질 수 있어요. rewrite_time 필드에는 쿼리와 모든 자식에 대한 누적 총 다시 작성 시간이 나노초 단위로 포함돼요. |
| profile.shards.searches.collector | 객체 배열 | 검색을 실행한 Lucene 컬렉터(collector)에 대한 프로파일링 정보예요. |
| profile.shards.aggregations | 객체 배열 | 집계 실행에 대한 프로파일링 정보예요. |
query 배열
query 배열에는 다음 필드를 가진 객체가 포함돼요.
| 필드 | 데이터 타입 | 설명 |
|---|---|---|
| type | String | 검색 쿼리가 다시 작성된 Lucene 쿼리 유형이에요. Lucene 클래스 이름에 해당해요(OpenSearch에서도 종종 같은 이름을 가져요). |
| description | String | 쿼리에 대한 Lucene 설명을 담고 있어요. 같은 유형의 쿼리를 구분하는 데 도움이 돼요. |
| time_in_nanos | Long | 이 쿼리의 총 경과 시간(나노초)이에요. 동시 세그먼트 검색의 경우 time_in_nanos는 모든 슬라이스에 걸친 총 시간(마지막으로 완료된 슬라이스 실행 종료 시간과 첫 번째 슬라이스 실행 시작 시간의 차이)이에요. |
| max_slice_time_in_nanos | Long | 쿼리를 실행하는 데 슬라이스가 걸린 최대 시간(나노초)이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| min_slice_time_in_nanos | Long | 쿼리를 실행하는 데 슬라이스가 걸린 최소 시간(나노초)이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| avg_slice_time_in_nanos | Long | 쿼리를 실행하는 데 슬라이스가 걸린 평균 시간(나노초)이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| breakdown | Object | 저수준 Lucene 실행에 대한 타이밍 통계를 담고 있어요. |
| children | 객체 배열 | 쿼리에 하위 쿼리(children)가 있다면 이 필드에 하위 쿼리에 대한 정보가 포함돼요. |
breakdown 객체
breakdown 객체는 저수준 Lucene 실행에 대한 타이밍 통계를 메서드별로 나눠서 나타내요. 타이밍은 벽시계 나노초로 표시되며 정규화되지 않아요. breakdown 타이밍은 모든 자식 시간을 포함해요. breakdown 객체는 다음 필드로 구성돼요. 모든 필드는 정수 값을 포함해요.
| 필드 | 설명 |
|---|---|
| create_weight | Lucene의 Query 객체는 불변이에요. 하지만 Lucene은 여러 IndexSearcher 객체에서 Query 객체를 재사용할 수 있어야 해요. 따라서 Query 객체는 쿼리가 실행되는 인덱스와 관련된 임시 상태와 통계를 유지해야 해요. 재사용을 달성하기 위해 모든 Query 객체는 <IndexSearcher, Query> 튜플과 관련된 임시 컨텍스트(상태)를 유지하는 Weight 객체를 생성해요. create_weight 필드에는 Weight 객체를 만드는 데 소요된 시간이 포함돼요. |
| build_scorer | Scorer는 일치하는 문서를 반복하며 각 문서에 대해 점수를 생성해요. build_scorer 필드에는 Scorer 객체를 생성하는 데 소요된 시간이 포함돼요. 여기에는 문서에 점수를 매기는 시간은 포함되지 않아요. Scorer 초기화 시간은 특정 쿼리의 최적화와 복잡성에 따라 달라져요. build_scorer 파라미터에는 쿼리에 캐싱이 적용 가능하고 활성화된 경우 캐싱과 관련된 시간도 포함돼요. |
| next_doc | next_doc Lucene 메서드는 쿼리와 일치하는 다음 문서의 문서 ID를 반환해요. 이 메서드는 advance 메서드의 특수한 종류로, advance(docId() + 1) 과 동일해요. next_doc 메서드는 많은 Lucene 쿼리에 더 편리해요. next_doc 필드에는 다음 일치 문서를 결정하는 데 필요한 시간이 포함되며, 이는 쿼리 유형에 따라 달라져요. |
| advance | advance 메서드는 Lucene의 next_doc 메서드의 더 저수준 버전이에요. 이것도 다음 일치 문서를 찾지만 호출 쿼리가 skip 식별 같은 추가 작업을 수행해야 해요. conjunction(Boolean 쿼리의 must 절) 같은 일부 쿼리는 next_doc 을 사용할 수 없어요. 그런 쿼리에는 advance 가 측정돼요. |
| match | 일부 쿼리의 경우 문서 일치가 두 단계로 수행돼요. 먼저 문서가 대략적으로 일치하는지 확인해요. 둘째, 대략 일치한 문서를 더 포괄적인 과정으로 검사해요. 예를 들어 phrase 쿼리는 문서에 구의 모든 용어가 포함되어 있는지 먼저 확인한 다음, 용어가 순서대로 있는지(더 비용이 드는 과정) 검증해요. match 필드는 두 단계 검증 과정을 사용하는 쿼리에서만 0이 아니에요. |
| score | Scorer가 특정 문서에 점수를 매기는 데 걸린 시간을 담고 있어요. |
| shallow_advance | advanceShallow Lucene 메서드를 실행하는 데 필요한 시간을 담고 있어요. |
| compute_max_score | getMaxScore Lucene 메서드를 실행하는 데 필요한 시간을 담고 있어요. |
| set_min_competitive_score | setMinCompetitiveScore Lucene 메서드를 실행하는 데 필요한 시간을 담고 있어요. |
| max_ |
쿼리 메서드를 실행하는 데 슬라이스가 걸린 최대 시간이에요. create_weight 메서드의 breakdown 통계에는 프로파일된 최대 시간이 포함되지 않는데, 이 메서드는 슬라이스 수준이 아니라 쿼리 수준에서 실행되기 때문이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| min_ |
쿼리 메서드를 실행하는 데 슬라이스가 걸린 최소 시간이에요. create_weight 메서드의 breakdown 통계에는 프로파일된 최소 시간이 포함되지 않는데, 이 메서드는 슬라이스 수준이 아니라 쿼리 수준에서 실행되기 때문이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| avg_ |
쿼리 메서드를 실행하는 데 슬라이스가 걸린 평균 시간이에요. create_weight 메서드의 breakdown 통계에는 프로파일된 평균 시간이 포함되지 않는데, 이 메서드는 슬라이스 수준이 아니라 쿼리 수준에서 실행되기 때문이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| max_ |
슬라이스에서 |
| min_ |
슬라이스에서 |
| avg_ |
슬라이스에서 |
collector 배열
collector 배열에는 Lucene Collector에 대한 정보가 포함돼요. Collector는 문서 탐색과 점수 매기를 조정하고 일치하는 문서를 수집하는 역할을 담당해요. Collector를 사용해 개별 쿼리는 집계 결과를 기록하고 전역 쿼리나 쿼리 후 필터(post-query filter)를 실행할 수 있어요.
| 필드 | 설명 |
|---|---|
| name | 컬렉터 이름이에요. 예제 응답 에서 컬렉터는 단일 SimpleTopScoreDocCollector — 기본 점수·정렬 컬렉터예요. |
| reason | 컬렉터에 대한 설명을 담고 있어요. 가능한 필드 값은 Collector 이유 를 참고하세요. |
| time_in_nanos | 이 컬렉터의 총 경과 시간(나노초)이에요. 동시 세그먼트 검색의 경우 time_in_nanos는 모든 슬라이스에 걸친 총 시간(마지막으로 완료된 슬라이스 실행 종료 시간과 첫 번째 슬라이스 실행 시작 시간의 차이)이에요. |
| children | 컬렉터에 하위 컬렉터(children)가 있다면 이 필드에 하위 컬렉터에 대한 정보가 포함돼요. |
| max_slice_time_in_nanos | 슬라이스가 걸린 최대 시간(나노초)이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| min_slice_time_in_nanos | 슬라이스가 걸린 최소 시간(나노초)이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| avg_slice_time_in_nanos | 슬라이스가 걸린 평균 시간(나노초)이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| slice_count | 이 쿼리의 총 슬라이스 수예요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| reduce_time_in_nanos | 모든 슬라이스 컬렉터의 결과를 줄이는(reduce) 데 걸린 시간(나노초)이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
Collector 시간은 독립적으로 계산, 결합, 정규화되므로 쿼리 시간과 독립적이에요.
Collector 이유 (Collector reasons)
다음 표는 사용 가능한 모든 컬렉터 이유를 설명해요.
| 이유 | 설명 |
|---|---|
| search_sorted | 문서에 점수를 매기고 정렬하는 컬렉터예요. 대부분의 단순 검색에 있어요. |
| search_count | 일치하는 문서 수를 세지만 소스를 가져오지 않는 컬렉터예요. size: 0 이 지정된 경우에 있어요. |
| search_terminate_after_count | 일치하는 문서를 검색하고 지정된 수의 문서를 찾으면 검색을 종료하는 컬렉터예요. terminate_after_count 쿼리 파라미터가 지정된 경우에 있어요. |
| search_min_score | 최소 점수보다 큰 점수를 가진 일치하는 문서를 반환하는 컬렉터예요. min_score 파라미터가 지정된 경우에 있어요. |
| search_multi | 다른 컬렉터를 위한 래퍼 컬렉터예요. 검색, 집계, 전역 집계, post 필터가 단일 검색에 결합된 경우에 있어요. |
| search_timeout | 지정된 시간이 지나면 실행을 멈추는 컬렉터예요. timeout 파라미터가 지정된 경우에 있어요. |
| aggregation | 지정된 쿼리 범위에 대해 실행되는 집계용 컬렉터예요. OpenSearch는 단일 집계 컬렉터를 사용해 모든 집계에 대한 문서를 수집해요. |
| global_aggregation | 전역 쿼리 범위에 대해 실행되는 컬렉터예요. 전역 범위는 지정된 쿼리 범위와 다르므로 전체 데이터 세트를 수집하려면 match_all 쿼리를 실행해야 해요. |
집계 응답
다음 예제들은 서로 다른 집계 유형의 프로파일링 응답을 보여줘요.
응답: 전역 집계
응답에는 프로파일링 정보가 포함돼요:
응답: 비전역 집계
응답에는 프로파일링 정보가 포함돼요:
응답 본문 필드
aggregations 배열에는 다음 필드를 가진 집계 객체가 포함돼요.
| 필드 | 데이터 타입 | 설명 |
|---|---|---|
| type | String | 집계기(aggregator) 유형이에요. 비전역 집계 예제 응답 에서 집계기 유형은 AvgAggregator 예요. 전역 집계 예제 응답 에는 AvgAggregator 자식이 있는 GlobalAggregator 가 포함돼요. |
| description | String | 집계에 대한 Lucene 설명을 담고 있어요. 같은 유형의 집계를 구분하는 데 도움이 돼요. |
| time_in_nanos | Long | 이 집계의 총 경과 시간(나노초)이에요. 동시 세그먼트 검색의 경우 time_in_nanos는 모든 슬라이스에 걸친 총 시간(마지막으로 완료된 슬라이스 실행 종료 시간과 첫 번째 슬라이스 실행 시작 시간의 차이)이에요. |
| breakdown | Object | 저수준 Lucene 실행에 대한 타이밍 통계를 담고 있어요. |
| children | 객체 배열 | 집계에 하위 집계(children)가 있다면 이 필드에 하위 집계에 대한 정보가 포함돼요. |
| debug | Object | 일부 집계는 기본 실행의 세부 사항을 설명하는 debug 객체를 반환해요. |
| max_slice_time_in_nanos | Long | 집계를 실행하는 데 슬라이스가 걸린 최대 시간(나노초)이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| min_slice_time_in_nanos | Long | 집계를 실행하는 데 슬라이스가 걸린 최소 시간(나노초)이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| avg_slice_time_in_nanos | Long | 집계를 실행하는 데 슬라이스가 걸린 평균 시간(나노초)이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
breakdown 객체
breakdown 객체는 저수준 Lucene 실행에 대한 타이밍 통계를 메서드별로 나눠서 나타내요. breakdown 객체의 각 필드는 집계 내에서 실행되는 내부 Lucene 메서드를 나타내요. 타이밍은 벽시계 나노초로 표시되며 정규화되지 않아요. breakdown 타이밍은 모든 자식 시간을 포함해요. breakdown 객체는 다음 필드로 구성돼요. 모든 필드는 정수 값을 포함해요.
| 필드 | 설명 |
|---|---|
| initialize | AggregationCollectorManager 생성 중 preCollection() 콜백 메서드를 실행하는 데 걸린 시간을 담고 있어요. 동시 세그먼트 검색의 경우 initialize 메서드에는 모든 슬라이스에 걸친 총 경과 시간(마지막으로 완료된 슬라이스 실행 종료 시간과 첫 번째 슬라이스 실행 시작 시간의 차이)이 포함돼요. |
| build_leaf_collector | 주어진 컨텍스트를 수집하는 새 컬렉터를 만드는 집계의 getLeafCollector() 메서드를 실행하는 데 걸린 시간을 담고 있어요. 동시 세그먼트 검색의 경우 build_leaf_collector 메서드에는 모든 슬라이스에 걸친 총 경과 시간(마지막으로 완료된 슬라이스 실행 종료 시간과 첫 번째 슬라이스 실행 시작 시간의 차이)이 포함돼요. |
| collect | 문서를 버킷으로 수집하는 데 걸린 시간을 담고 있어요. 동시 세그먼트 검색의 경우 collect 메서드에는 모든 슬라이스에 걸친 총 경과 시간(마지막으로 완료된 슬라이스 실행 종료 시간과 첫 번째 슬라이스 실행 시작 시간의 차이)이 포함돼요. |
| post_collection | 집계의 postCollection() 콜백 메서드를 실행하는 데 걸린 시간을 담고 있어요. 동시 세그먼트 검색의 경우 post_collection 메서드에는 모든 슬라이스에 걸친 총 경과 시간(마지막으로 완료된 슬라이스 실행 종료 시간과 첫 번째 슬라이스 실행 시작 시간의 차이)이 포함돼요. |
| build_aggregation | 이 집계의 결과를 만드는 집계의 buildAggregations() 메서드를 실행하는 데 걸린 시간을 담고 있어요. 동시 세그먼트 검색의 경우 build_aggregation 메서드에는 모든 슬라이스에 걸친 총 경과 시간(마지막으로 완료된 슬라이스 실행 종료 시간과 첫 번째 슬라이스 실행 시작 시간의 차이)이 포함돼요. |
| reduce | reduce 단계에 걸린 시간을 담고 있어요. 동시 세그먼트 검색의 경우 reduce 메서드에는 모든 슬라이스에 걸친 총 경과 시간(마지막으로 완료된 슬라이스 실행 종료 시간과 첫 번째 슬라이스 실행 시작 시간의 차이)이 포함돼요. |
| max_ |
집계 메서드를 실행하는 데 슬라이스가 걸린 최대 시간이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| min_ |
집계 메서드를 실행하는 데 슬라이스가 걸린 최소 시간이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| avg_ |
집계 메서드를 실행하는 데 슬라이스가 걸린 평균 시간이에요. 이 필드는 동시 세그먼트 검색을 활성화한 경우에만 포함돼요. |
| 모든 슬라이스에 걸친 총 메서드 횟수예요. 예를 들어 collect 메서드의 경우 모든 슬라이스에서 문서를 버킷으로 수집하는 데 필요한 이 메서드의 총 호출 횟수예요. | |
| max_ |
슬라이스에서 |
| min_ |
슬라이스에서 |
| avg_ |
슬라이스에서 |
출처: 문서