Anatomy of a workload
출처: 문서
본문
Anatomy of a workload
워크로드는 하나 이상의 벤치마킹 시나리오에 대한 명세예요. 모든 워크로드는 다음 파일과 디렉터리를 포함해요:
workload.json: 모든 워크로드 설정을 포함해요.index.json: 문서 매핑, 파라미터, 인덱스 설정을 포함해요.files.txt: 데이터 코퍼스 파일 이름을 포함해요._test-procedures: 대부분의 워크로드는default.json에 구성된 하나의 기본 테스트 프로시저만 포함해요._operations: 테스트 프로시저에서 사용되는 모든 작업을 포함해요.workload.py: 테스트에 더 동적인 기능을 추가해요.
workload.json
workload.json 파일은 보통 다음 요소를 포함해요:
indices: 워크로드에 사용되는 관련 인덱스와 인덱스 템플릿을 정의해요. 인덱스를 생성하려면name을 지정하세요. 인덱스에 정의를 추가하려면body옵션을 사용하고 인덱스 정의가 포함된 JSON 파일을 가리키세요.corpora: 워크로드에 사용되는 모든 문서 코퍼스를 정의해요. 여기에는 문서가 포함된 소스 파일과 각 파일의 문서 수가 포함돼요.operations: 선택 사항. 워크로드가 수행하는 OpenSearch API 작업과 해당 작업이 매개변수화되는 방식을 나열해요. 예를 들어, OpenSearch Benchmark가 문서를 쓸 수 있는 벤치마크 클러스터에 인덱스를 생성하는create-index라는 작업을 나열할 수 있어요.schedule: 작업과 작업이 인라인으로 실행되는 순서를 정의해요. 또는operations를 사용하여 작업을 그룹화하고test_procedures매개변수로 작업 순서를 지정할 수 있어요.
다음 예제 워크로드는 이러한 요소가 함께 작동하는 모습을 보여줘요. 이 워크로드를 자신의 벤치마크 구성에서 실행할 수 있어요:
{
"description": "Tutorial benchmark for OpenSearch Benchmark",
"indices": [
{
"name": "movies",
"body": "index.json"
}
],
"corpora": [
{
"name": "movies",
"documents": [
{
"source-file": "movies-documents.json",
"document-count": 11658903, # Fetch document count from command line
"uncompressed-bytes": 1544799789 # Fetch uncompressed bytes from command line
}
]
}
],
"schedule": [
{
"operation": {
"operation-type": "create-index"
}
},
{
"operation": {
"operation-type": "cluster-health",
"request-params": {
"wait_for_status": "green"
},
"retry-until-success": true
}
},
{
"operation": {
"operation-type": "bulk",
"bulk-size": 5000
},
"warmup-time-period": 120,
"clients": 8
},
{
"operation": {
"name": "query-match-all",
"operation-type": "search",
"body": {
"query": {
"match_all": {}
}
}
},
"iterations": 1000,
"target-throughput": 100
}
]
}
index.json
index.json 파일은 create-index 작업 중 워크로드 문서에 대한 데이터 매핑, 인덱싱 파라미터, 인덱스 설정을 정의해요.
OpenSearch Benchmark가 워크로드용 인덱스를 생성할 때 index.json 파일의 인덱스 설정과 매핑 템플릿을 사용해요. index.json 파일의 매핑은 files.txt 파일에 저장된 워크로드 코퍼스의 단일 문서 매핑을 기반으로 해요. 다음은 nyc_taxis 워크로드의 index.json 파일 예시예요. number_of_shards, number_of_replicas, query_cache_enabled, requests_cache_enabled 같은 필드를 사용자 지정할 수 있어요.
{
"settings": {
"index.number_of_shards": {% raw %}{{number_of_shards | default(1)}}{% endraw %},
"index.number_of_replicas": {% raw %}{{number_of_replicas | default(0)}}{% endraw %},
"index.queries.cache.enabled": {% raw %}{{query_cache_enabled | default(false) | tojson}}{% endraw %},
"index.requests.cache.enable": {% raw %}{{requests_cache_enabled | default(false) | tojson}}{% endraw %}
},
"mappings": {
"_source": {
"enabled": {% raw %}{{ source_enabled | default(true) | tojson }}{% endraw %}
},
"properties": {
"surcharge": {
"scaling_factor": 100,
"type": "scaled_float"
},
"dropoff_datetime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"trip_type": {
"type": "keyword"
},
"mta_tax": {
"scaling_factor": 100,
"type": "scaled_float"
},
"rate_code_id": {
"type": "keyword"
},
"passenger_count": {
"type": "integer"
},
"pickup_datetime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"tolls_amount": {
"scaling_factor": 100,
"type": "scaled_float"
},
"tip_amount": {
"type": "half_float"
},
"payment_type": {
"type": "keyword"
},
"extra": {
"scaling_factor": 100,
"type": "scaled_float"
},
"vendor_id": {
"type": "keyword"
},
"store_and_fwd_flag": {
"type": "keyword"
},
"improvement_surcharge": {
"scaling_factor": 100,
"type": "scaled_float"
},
"fare_amount": {
"scaling_factor": 100,
"type": "scaled_float"
},
"ehail_fee": {
"scaling_factor": 100,
"type": "scaled_float"
},
"cab_color": {
"type": "keyword"
},
"dropoff_location": {
"type": "geo_point"
},
"vendor_name": {
"type": "text"
},
"total_amount": {
"scaling_factor": 100,
"type": "scaled_float"
},
"trip_distance": {% raw %}{%- if trip_distance_mapping is defined %} {{ trip_distance_mapping | tojson }} {%- else %}{% endraw %} {
"scaling_factor": 100,
"type": "scaled_float"
}{% raw %}{%- endif %}{% endraw %},
"pickup_location": {
"type": "geo_point"
}
},
"dynamic": "strict"
}
}
files.txt
files.txt 파일은 워크로드 데이터를 저장하는 파일을 나열해요. 이 파일들은 일반적으로 압축된 JSON 파일로 저장돼요.
_operations and _test-procedures
워크로드를 더 읽기 쉽게 만들기 위해 _operations와 _test-procedures가 두 개의 디렉터리로 분리되어 있어요.
_operations 디렉터리에는 테스트 프로시저가 사용할 수 있는 모든 지원 작업을 나열하는 default.json 파일이 포함되어 있어요. nyc_taxis 같은 일부 워크로드는 snapshot 작업 같은 기능별 작업을 나열하는 추가 .json 파일을 포함해요. 다음 JSON 예제는 nyc_taxis 워크로드의 작업 목록을 보여줘요:
{
"name": "index",
"operation-type": "bulk",
"bulk-size": {% raw %}{{bulk_size | default(10000)}}{% endraw %},
"ingest-percentage": {% raw %}{{ingest_percentage | default(100)}}{% endraw %}
},
{
"name": "update",
"operation-type": "bulk",
"bulk-size": {% raw %}{{bulk_size | default(10000)}},
"ingest-percentage": {{ingest_percentage | default(100)}},
"conflicts": "{{conflicts | default('random')}}",
"on-conflict": "{{on_conflict | default('update')}}",
"conflict-probability": {{conflict_probability | default(25)}},
"recency": {{recency | default(0)}}{% endraw %}
},
{
"name": "wait-until-merges-finish",
"operation-type": "index-stats",
"index": "_all",
"condition": {
"path": "_all.total.merges.current",
"expected-value": 0
},
"retry-until-success": true,
"include-in-reporting": false
},
{
"name": "default",
"operation-type": "search",
"body": {
"query": {
"match_all": {}
}
}
},
{
"name": "range",
"operation-type": "search",
"body": {
"query": {
"range": {
"total_amount": {
"gte": 5,
"lt": 15
}
}
}
}
},
{
"name": "distance_amount_agg",
"operation-type": "search",
"body": {
"size": 0,
"query": {
"bool": {
"filter": {
"range": {
"trip_distance": {
"lt": 50,
"gte": 0
}
}
}
}
},
"aggs": {
"distance_histo": {
"histogram": {
"field": "trip_distance",
"interval": 1
},
"aggs": {
"total_amount_stats": {
"stats": {
"field": "total_amount"
}
}
}
}
}
}
},
{
"name": "autohisto_agg",
"operation-type": "search",
"body": {
"size": 0,
"query": {
"range": {
"dropoff_datetime": {
"gte": "01/01/2015",
"lte": "21/01/2015",
"format": "dd/MM/yyyy"
}
}
},
"aggs": {
"dropoffs_over_time": {
"auto_date_histogram": {
"field": "dropoff_datetime",
"buckets": 20
}
}
}
}
},
{
"name": "date_histogram_agg",
"operation-type": "search",
"body": {
"size": 0,
"query": {
"range": {
"dropoff_datetime": {
"gte": "01/01/2015",
"lte": "21/01/2015",
"format": "dd/MM/yyyy"
}
}
},
"aggs": {
"dropoffs_over_time": {
"date_histogram": {
"field": "dropoff_datetime",
"calendar_interval": "day"
}
}
}
}
},
{
"name": "date_histogram_calendar_interval",
"operation-type": "search",
"body": {
"size": 0,
"query": {
"range": {
"dropoff_datetime": {
"gte": "2015-01-01 00:00:00",
"lt": "2016-01-01 00:00:00"
}
}
},
"aggs": {
"dropoffs_over_time": {
"date_histogram": {
"field": "dropoff_datetime",
"calendar_interval": "month"
}
}
}
}
},
{
"name": "date_histogram_calendar_interval_with_tz",
"operation-type": "search",
"body": {
"size": 0,
"query": {
"range": {
"dropoff_datetime": {
"gte": "2015-01-01 00:00:00",
"lt": "2016-01-01 00:00:00"
}
}
},
"aggs": {
"dropoffs_over_time": {
"date_histogram": {
"field": "dropoff_datetime",
"calendar_interval": "month",
"time_zone": "America/New_York"
}
}
}
}
},
{
"name": "date_histogram_fixed_interval",
"operation-type": "search",
"body": {
"size": 0,
"query": {
"range": {
"dropoff_datetime": {
"gte": "2015-01-01 00:00:00",
"lt": "2016-01-01 00:00:00"
}
}
},
"aggs": {
"dropoffs_over_time": {
"date_histogram": {
"field": "dropoff_datetime",
"fixed_interval": "60d"
}
}
}
}
},
{
"name": "date_histogram_fixed_interval_with_tz",
"operation-type": "search",
"body": {
"size": 0,
"query": {
"range": {
"dropoff_datetime": {
"gte": "2015-01-01 00:00:00",
"lt": "2016-01-01 00:00:00"
}
}
},
"aggs": {
"dropoffs_over_time": {
"date_histogram": {
"field": "dropoff_datetime",
"fixed_interval": "60d",
"time_zone": "America/New_York"
}
}
}
}
},
{
"name": "date_histogram_fixed_interval_with_metrics",
"operation-type": "search",
"body": {
"size": 0,
"query": {
"range": {
"dropoff_datetime": {
"gte": "2015-01-01 00:00:00",
"lt": "2016-01-01 00:00:00"
}
}
},
"aggs": {
"dropoffs_over_time": {
"date_histogram": {
"field": "dropoff_datetime",
"fixed_interval": "60d"
},
"aggs": {
"total_amount": { "stats": { "field": "total_amount" } },
"tip_amount": { "stats": { "field": "tip_amount" } },
"trip_distance": { "stats": { "field": "trip_distance" } }
}
}
}
}
},
{
"name": "auto_date_histogram",
"operation-type": "search",
"body": {
"size": 0,
"query": {
"range": {
"dropoff_datetime": {
"gte": "2015-01-01 00:00:00",
"lt": "2016-01-01 00:00:00"
}
}
},
"aggs": {
"dropoffs_over_time": {
"auto_date_histogram": {
"field": "dropoff_datetime",
"buckets": "12"
}
}
}
}
},
{
"name": "auto_date_histogram_with_tz",
"operation-type": "search",
"body": {
"size": 0,
"query": {
"range": {
"dropoff_datetime": {
"gte": "2015-01-01 00:00:00",
"lt": "2016-01-01 00:00:00"
}
}
},
"aggs": {
"dropoffs_over_time": {
"auto_date_histogram": {
"field": "dropoff_datetime",
"buckets": "13",
"time_zone": "America/New_York"
}
}
}
}
},
{
"name": "auto_date_histogram_with_metrics",
"operation-type": "search",
"body": {
"size": 0,
"query": {
"range": {
"dropoff_datetime": {
"gte": "2015-01-01 00:00:00",
"lt": "2016-01-01 00:00:00"
}
}
},
"aggs": {
"dropoffs_over_time": {
"auto_date_histogram": {
"field": "dropoff_datetime",
"buckets": "12"
},
"aggs": {
"total_amount": { "stats": { "field": "total_amount" } },
"tip_amount": { "stats": { "field": "tip_amount" } },
"trip_distance": { "stats": { "field": "trip_distance" } }
}
}
}
}
},
{
"name": "desc_sort_tip_amount",
"operation-type": "search",
"index": "nyc_taxis",
"body": {
"query": {
"match_all": {}
},
"sort" : [
{"tip_amount" : "desc"}
]
}
},
{
"name": "asc_sort_tip_amount",
"operation-type": "search",
"index": "nyc_taxis",
"body": {
"query": {
"match_all": {}
},
"sort" : [
{"tip_amount" : "asc"}
]
}
}
_test-procedures 디렉터리에는 워크로드가 수행하는 작업 순서를 설정하는 default.json 파일이 포함되어 있어요. _operations 디렉터리와 마찬가지로 _test-procedures 디렉터리에도 nyc_taxis의 searchable_snapshots.json 같은 기능별 테스트 프로시저가 포함될 수 있어요. 다음 예제는 nyc_taxis의 검색 가능한 스냅샷 테스트 프로시저를 보여줘요:
{
"name": "searchable-snapshot",
"description": "Measuring performance for Searchable Snapshot feature. Based on the default test procedure 'append-no-conflicts'.",
"schedule": [
{
"operation": "delete-index"
},
{
"operation": {
"operation-type": "create-index",
"settings": {% raw %}{%- if index_settings is defined %} {{ index_settings | tojson }} {%- else %}{
"index.codec": "best_compression",
"index.refresh_interval": "30s",
"index.translog.flush_threshold_size": "4g"
}{%- endif %}{% endraw %}
}
},
{
"name": "check-cluster-health",
"operation": {
"operation-type": "cluster-health",
"index": "nyc_taxis",
"request-params": {
"wait_for_status": {% raw %}"{{ cluster_health | default('green') }}"{% endraw %},
"wait_for_no_relocating_shards": "true"
},
"retry-until-success": true
}
},
{
"operation": "index",
"warmup-time-period": 240,
"clients": {% raw %}{{ bulk_indexing_clients | default(8) }},
"ignore-response-error-level": "{{ error_level | default('non-fatal') }}"{% endraw %}
},
{
"name": "refresh-after-index",
"operation": "refresh"
},
{
"operation": {
"operation-type": "force-merge",
"request-timeout": 7200
{% raw %}{%- if force_merge_max_num_segments is defined %}{% endraw %},
"max-num-segments": {% raw %}{{ force_merge_max_num_segments | tojson }}{% endraw %}
{% raw %}{%- endif %}{% endraw %}
}
},
{
"name": "refresh-after-force-merge",
"operation": "refresh"
},
{
"operation": "wait-until-merges-finish"
},
{
"operation": "create-snapshot-repository"
},
{
"operation": "delete-snapshot"
},
{
"operation": "create-snapshot"
},
{
"operation": "wait-for-snapshot-creation"
},
{
"operation": {
"name": "delete-local-index",
"operation-type": "delete-index"
}
},
{
"operation": "restore-snapshot"
},
{
"operation": "default",
"warmup-iterations": 50,
"iterations": 100
{% raw %}{%- if not target_throughput %}{% endraw %}
,"target-throughput": 3
{% raw %}{%- elif target_throughput is string and target_throughput.lower() == 'none' %}{% endraw %}
{% raw %}{%- else %}{% endraw %}
,"target-throughput": {% raw %}{{ target_throughput | tojson }}{% endraw %}
{% raw %}{%- endif %}{% endraw %}
{% raw %}{%-if search_clients is defined and search_clients %}{% endraw %}
,"clients": {% raw %}{{ search_clients | tojson}}{% endraw %}
{% raw %}{%- endif %}{% endraw %}
},
{
"operation": "range",
"warmup-iterations": 50,
"iterations": 100
{% raw %}{%- if not target_throughput %}{% endraw %}
,"target-throughput": 0.7
{% raw %}{%- elif target_throughput is string and target_throughput.lower() == 'none' %}{% endraw %}
{% raw %}{%- else %}{% endraw %}
,"target-throughput": {% raw %}{{ target_throughput | tojson }}{% endraw %}
{% raw %}{%- endif %}{% endraw %}
{% raw %}{%-if search_clients is defined and search_clients %}{% endraw %}
,"clients": {% raw %}{{ search_clients | tojson}}{% endraw %}
{% raw %}{%- endif %}{% endraw %}
},
{
"operation": "distance_amount_agg",
"warmup-iterations": 50,
"iterations": 50
{% raw %}{%- if not target_throughput %}{% endraw %}
,"target-throughput": 2
{% raw %}{%- elif target_throughput is string and target_throughput.lower() == 'none' %}{% endraw %}
{% raw %}{%- else %}{% endraw %}
,"target-throughput": {% raw %}{{ target_throughput | tojson }}{% endraw %}
{% raw %}{%- endif %}{% endraw %}
{% raw %}{%-if search_clients is defined and search_clients %}{% endraw %}
,"clients": {% raw %}{{ search_clients | tojson}}{% endraw %}
{% raw %}{%- endif %}{% endraw %}
},
{
"operation": "autohisto_agg",
"warmup-iterations": 50,
"iterations": 100
{% raw %}{%- if not target_throughput %}{% endraw %}
,"target-throughput": 1.5
{% raw %}{%- elif target_throughput is string and target_throughput.lower() == 'none' %}{% endraw %}
{% raw %}{%- else %}{% endraw %}
,"target-throughput": {% raw %}{{ target_throughput | tojson }}{% endraw %}
{% raw %}{%- endif %}{% endraw %}
{% raw %}{%-if search_clients is defined and search_clients %}{% endraw %}
,"clients": {% raw %}{{ search_clients | tojson}}{% endraw %}
{% raw %}{%- endif %}{% endraw %}
},
{
"operation": "date_histogram_agg",
"warmup-iterations": 50,
"iterations": 100
{% raw %}{%- if not target_throughput %}{% endraw %}
,"target-throughput": 1.5
{% raw %}{%- elif target_throughput is string and target_throughput.lower() == 'none' %}{% endraw %}
{% raw %}{%- else %}{% endraw %}
,"target-throughput": {% raw %}{{ target_throughput | tojson }}{% endraw %}
{% raw %}{%- endif %}{% endraw %}
{% raw %}{%-if search_clients is defined and search_clients %}{% endraw %}
,"clients": {% raw %}{{ search_clients | tojson}}{% endraw %}
{% raw %}{%- endif %}{% endraw %}
}
]
}
Workload examples
다음 예제는 자신의 워크로드에 맞게 조정할 수 있는 완전한 workload.json 파일을 보여줘요.
Running unthrottled
다음 예제에서 OpenSearch Benchmark는 movies 인덱스에 대해 1시간 동안 제한 없는 벌크 인덱스 작업을 실행해요:
{
"description": "Tutorial benchmark for OpenSearch Benchmark",
"indices": [
{
"name": "movies",
"body": "index.json"
}
],
"corpora": [
{
"name": "movies",
"documents": [
{
"source-file": "movies-documents.json",
"document-count": 11658903, # Fetch document count from command line
"uncompressed-bytes": 1544799789 # Fetch uncompressed bytes from command line
}
]
}
],
"schedule": [
{
"operation": "bulk",
"warmup-time-period": 120,
"time-period": 3600,
"clients": 8
}
]
}
Workload with a single task
다음 워크로드는 단일 작업(match_all 쿼리)으로 벤치마크를 실행해요. clients가 지정되지 않았으므로 하나의 클라이언트만 사용돼요. schedule에 따라 워크로드는 1개 클라이언트로 초당 10회 작업으로 match_all 쿼리를 실행하고, 100회 반복으로 워밍업한 후 다음 100회 반복으로 벤치마크를 측정해요:
{
"description": "Tutorial benchmark for OpenSearch Benchmark",
"indices": [
{
"name": "movies",
"body": "index.json"
}
],
"corpora": [
{
"name": "movies",
"documents": [
{
"source-file": "movies-documents.json",
"document-count": 11658903, # Fetch document count from command line
"uncompressed-bytes": 1544799789 # Fetch uncompressed bytes from command line
}
]
}
],
"schedule": [
{
"operation": {
"operation-type": "search",
"index": "_all",
"body": {
"query": {
"match_all": {}
}
}
},
"warmup-iterations": 100,
"iterations": 100,
"target-throughput": 10
}
]
}
Next steps
- 각 사전 패키지 워크로드의 데이터, 클러스터 요구 사항, 쿼리 유형은 Workload types를 참조하세요.
- 자신의 워크로드를 생성하는 방법에 대한 정보는 Creating custom workloads를 참조하세요.