2026-02-18 23:05:24Elasticsearch最佳实践:不同版本之间的存储成本对比
作为日志分析场景中最广泛使用的技术解决方案之一,Elasticsearch经常被竞争对手进行比较。特别是随着日志数据量的增加,日志场景中广泛比较的核心指标包括数据写入吞吐量、存储成本、查询速度和分析能力。作为一个不断创新和迭代的产品,Elasticsearch 在日志分析场景中不断引入不同的新功能,以满足客户在日志场景中不断增长的需求。
Elasticsearch多版本间的性能更新然而,竞争对手常常误导性地使用低版本的 Elasticsearch 进行基准测试,然后进行指标对比,并得出其比 Elasticsearch 更为优秀的结论。这种比较大多数时候是非常不客观的,也是具有误导的,要知道 6.x 版本已经过时,而 7.10 版本也已经发布了很长一段时间。在8.8到7.10之间的15个版本当中,Elasticsearch 发布了非常多的性能优化特性,因此,为了帮助用户更好地了解最新版本的Elasticsearch所具备的功能,我将在本文之后的一系列文章中从多个维度比较旧版本和新版本的 Elasticsearch,以帮助我们的用户在进行技术选择时做出更准确的评估,并提供精确的数据。
测试前置条件在本文中,我们将比较 Elasticsearch 在存储日志数据和指标数据方面,在版本6、版本7和版本8之间的差异。注意,这里的比较,将不做任何的配置上的优化,也就是说,在不开启任何场景调优选项的情况下,单纯比较版本间,在相同数据集上的默认存储消耗。而在接下去的系列文章中,我们再根据场景,进行场景优化。
数据源和版本选择为了尽可能真实地呈现实际环境中的情况,我们将使用由 Apache SkyWalking showcase 生成的日志和指标数据作为我们的数据来源。在选择 Elasticsearch 的版本时,我们会选择最广泛使用的版本,而不会涉及所有子版本。对于6.x版本,我们将选择6.8作为测试版本;对于7.x版本,我们将选择7.10。这主要是因为在7.10版本中,Elastic进行了许可证的更改,使其成为许多云服务提供商支持的 Elasticsearch 版本的分水岭。同时,我们注意到 Opensearch 也是从这个版本中分支出来的。至于8.x版本,我们将使用腾讯云提供的最新版本8.8.1。
配置在测试过程中,我们将专注于对 SkyWalking 的原始配置进行测试,而不涉及任何索引层面的优化。我们这样做的目的是为了验证在不掌握专业 Elasticsearch 调优知识的情况下,仅通过对Elasticsearch进行升级,是否能够达到预期的效果。这种方法能够提供清晰而直观的结果,同时也帮助我们了解在不进行索引层面的优化情况下,Elasticsearch的性能表现如何。
在测试开始之前,我们会确保不同版本的集群使用相同的数据结构来存储数据。这意味着我们会将索引的mapping分别拷贝到三个集群上,并使用同样的数据,即将相同的索引数据写入三个集群。
这里,我们首先将 SkyWalking 上的数据写入Elasticsearch 8.8.1集群,然后进行数据镜像,将数据拷贝到6.8和7.10集群。这样,数据的模式、数量和内容都是相同的。同时,我们将配置相同的压缩参数(默认值)并将索引进行一次段合并。
日志数据对比以下是 SkyWalking 日志数据的schema:
代码语言:json复制{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1,
"analysis": {
"analyzer": {
"oap_log_analyzer": {
"type": "standard"
}
}
}
},
"mappings": {
"_source": {
"excludes": [
"tags"
]
},
"properties": {
"content": {
"type": "text",
"copy_to": [
"content_match"
]
},
"content_match": {
"type": "text",
"analyzer": "oap_log_analyzer"
},
"content_type": {
"type": "integer",
"index": false
},
"endpoint_id": {
"type": "keyword"
},
"service_id": {
"type": "keyword"
},
"service_instance_id": {
"type": "keyword"
},
"span_id": {
"type": "integer"
},
"tags": {
"type": "keyword"
},
"tags_raw_data": {
"type": "binary"
},
"time_bucket": {
"type": "long"
},
"timestamp": {
"type": "long"
},
"trace_id": {
"type": "keyword"
},
"trace_segment_id": {
"type": "keyword"
},
"unique_id": {
"type": "keyword"
}
}
}
}这个索引有5个分片和0个副本,使用了一个自定义的分析器oap_log_analyzer。这个索引有15个字段,大致可以分为以下几类:文本类型(text):这些字段用来存储需要分词的字符串,比如content。这些字段可以用来进行全文检索、模糊匹配等操作。关键词类型(keyword):这些字段用来存储不需要分词的字符串,比如endpoint_id、service_id等。这些字段可以用来进行精确匹配、排序、聚合等操作。数值类型(integer、long等):这些字段用来存储整数或长整数,比如content_type、span_id等。这些字段可以用来进行数值比较、范围查询、聚合等操作。二进制类型(binary):这些字段用来存储二进制数据,比如tags_raw_data。这些字段不会被索引或搜索,只能用于存储或检索。复制类型(copy_to):这些字段用来存储其他字段的值的副本,比如content_match。这些字段可以用来进行多字段查询。分析器类型(analyzer):这些字段用来指定使用哪种分析器来处理文本,比如content_match。这些字段可以用不同的分词规则来影响搜索结果。样例为:
代码语言:javascript复制 {
"_index": "sw_log-20231023",
"_id": "fe620a61abca48b394358015a04a55b8",
"_score": 1,
"_source": {
"trace_id": "9ad5dfed-1def-4ed3-b233-5dce5afa66c8",
"unique_id": "fe620a61abca48b394358015a04a55b8",
"span_id": 0,
"endpoint_id": "c29uZ3M=.1_VW5kZXJ0b3dEaXNwYXRjaA==",
"service_instance_id": "c29uZ3M=.1_Mzg0ZWZlYWE2NzFjNGFhYjg2ZGFmZjA3OWE4YjljYzZAMTcyLjIyLjAuNg==",
"content": """2023-10-23 23:59:49.247 [TID:9ad5dfed-1def-4ed3-b233-5dce5afa66c8] [XNIO-1 task-2] INFO o.a.s.s.s.s.c.SongController -Listing top songs
""",
"trace_segment_id": "7e097591b9b74531a14df130f17087a8.54.16981055892474632",
"content_type": 1,
"tags_raw_data": "Cg0KBWxldmVsEgRJTkZPClAKBmxvZ2dlchJGb3JnLmFwYWNoZS5za3l3YWxraW5nLnNob3djYXNlLnNlcnZpY2VzLnNvbmcuY29udHJvbGxlci5Tb25nQ29udHJvbGxlcgoXCgZ0aHJlYWQSDVhOSU8tMSB0YXNrLTI=",
"service_id": "c29uZ3M=.1",
"time_bucket": 20231023235949,
"timestamp": 1698105589247
}
}我们分别在6.8,7.10,8.8的集群上写入相同的数据,通过_stats/store,segments接口,我们得到三个版本的索引统计信息的区别:
版本
文档数量
存储大小
段数量
内存占用
6.8
166138
91888073字节
5
420658字节
7.10
166138
89639942字节
5
16580字节
8.8
166138
78307161字节
5
0字节
从表格中可以看出,以下是一些主要的区别:
存储大小随着版本的升级而减少,这是因为Elasticsearch对索引结构和压缩算法进行了优化。相对于6.8版本,8.8版本的存储优化百分比为 ≈14.78%相对于7.10版本,8.8版本的存储优化百分比为 ≈12.64%内存占用从6.8到7.10大幅减少,再到到8.8变为0,这是因为Elasticsearch对内存管理进行了改进,即进行了heap-offload,也更改了加载的方式
日志 6.8日志 7.10日志 8.8指标数据对比以下是 SkyWalking 指标数据的schema:
代码语言:json复制{
"settings": {
"number_of_replicas": 1,
"number_of_shards": 1,
"analysis": {
"analyzer": {
"oap_analyzer": {
"type": "standard"
}
}
}
},
"mappings": {
"properties": {
"address": {
"type": "keyword"
},
"agent_id": {
"type": "keyword"
},
"component_id": {
"type": "integer",
"index": false
},
"component_ids": {
"type": "keyword",
"index": false
},
"count": {
"type": "long",
"index": false
},
"dataset": {
"type": "text",
"index": false
},
"datatable_count": {
"type": "text",
"index": false
},
"datatable_summation": {
"type": "text",
"index": false
},
"datatable_value": {
"type": "text",
"index": false
},
"denominator": {
"type": "long"
},
"dest_endpoint": {
"type": "keyword"
},
"dest_process_id": {
"type": "keyword"
},
"dest_service_id": {
"type": "keyword"
},
"dest_service_instance_id": {
"type": "keyword"
},
"detect_type": {
"type": "integer"
},
"double_summation": {
"type": "double",
"index": false
},
"double_value": {
"type": "double"
},
"ebpf_profiling_schedule_id": {
"type": "keyword"
},
"end_time": {
"type": "long"
},
"endpoint": {
"type": "keyword"
},
"endpoint_traffic_name": {
"type": "keyword",
"copy_to": [
"endpoint_traffic_name_match"
]
},
"endpoint_traffic_name_match": {
"type": "text",
"analyzer": "oap_analyzer"
},
"entity_id": {
"type": "keyword"
},
"instance_id": {
"type": "keyword"
},
"instance_traffic_name": {
"type": "keyword",
"index": false
},
"int_value": {
"type": "integer"
},
"label": {
"type": "keyword"
},
"labels_json": {
"type": "keyword",
"index": false
},
"last_ping": {
"type": "long"
},
"last_update_time_bucket": {
"type": "long"
},
"layer": {
"type": "integer"
},
"match": {
"type": "long",
"index": false
},
"message": {
"type": "keyword"
},
"metric_table": {
"type": "keyword"
},
"name": {
"type": "keyword"
},
"numerator": {
"type": "long"
},
"parameters": {
"type": "keyword",
"index": false
},
"percentage": {
"type": "integer"
},
"precision": {
"type": "integer",
"index": false
},
"process_id": {
"type": "keyword"
},
"profiling_support_status": {
"type": "integer"
},
"properties": {
"type": "text",
"index": false
},
"remote_service_name": {
"type": "keyword"
},
"represent_service_id": {
"type": "keyword"
},
"represent_service_instance_id": {
"type": "keyword"
},
"s_num": {
"type": "long",
"index": false
},
"service": {
"type": "keyword"
},
"service_group": {
"type": "keyword"
},
"service_id": {
"type": "keyword"
},
"service_instance": {
"type": "keyword"
},
"service_instance_id": {
"type": "keyword"
},
"service_name": {
"type": "keyword"
},
"service_traffic_name": {
"type": "keyword",
"copy_to": [
"service_traffic_name_match"
]
},
"service_traffic_name_match": {
"type": "text",
"analyzer": "oap_analyzer"
},
"short_name": {
"type": "keyword"
},
"source_endpoint": {
"type": "keyword"
},
"source_process_id": {
"type": "keyword"
},
"source_service_id": {
"type": "keyword"
},
"source_service_instance_id": {
"type": "keyword"
},
"span_name": {
"type": "keyword"
},
"start_time": {
"type": "long"
},
"summation": {
"type": "long",
"index": false
},
"t_num": {
"type": "long",
"index": false
},
"tag_key": {
"type": "keyword"
},
"tag_type": {
"type": "keyword"
},
"tag_value": {
"type": "keyword"
},
"task_id": {
"type": "keyword"
},
"time_bucket": {
"type": "long"
},
"total": {
"type": "long",
"index": false
},
"total_num": {
"type": "long",
"index": false
},
"type": {
"type": "keyword"
},
"uuid": {
"type": "keyword"
},
"value": {
"type": "long"
}
}
}
}这个索引有一个副本和一个分片,使用了一个自定义的分析器oap_analyzer。这个索引有很多字段,大致可以分为以下几类:关键词类型(keyword):这些字段用来存储不需要分词的字符串,比如address、agent_id、dest_endpoint等。这些字段可以用来进行精确匹配、排序、聚合等操作。文本类型(text):这些字段用来存储需要分词的字符串,比如dataset、datatable_count、datatable_summation等。这些字段可以用来进行全文检索、模糊匹配等操作。数值类型(integer、long、double等):这些字段用来存储整数或浮点数,比如component_id、count、double_value等。这些字段可以用来进行数值比较、范围查询、聚合等操作。二进制类型(binary):这些字段用来存储二进制数据,比如uuid。这些字段不会被索引或搜索,只能用于存储或检索。复制类型(copy_to):这些字段用来存储其他字段的值的副本,比如endpoint_traffic_name_match、service_traffic_name_match等。这些字段可以用来进行多字段查询。分析器类型(analyzer):这些字段用来指定使用哪种分析器来处理文本,比如endpoint_traffic_name_match、service_traffic_name_match等。这些字段可以用不同的分词规则来影响搜索结果。样例数据为:
代码语言:json复制{
"_index": "sw_metrics-all-20231023",
"_id": "meter_datasource_202310230003_c29uZ3M=.1_Mzg0ZWZlYWE2NzFjNGFhYjg2ZGFmZjA3OWE4YjljYzZAMTcyLjIyLjAuNg==",
"_score": 1,
"_source": {
"metric_table": "meter_datasource",
"datatable_summation": "8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-minimumIdle,30|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-threadsAwaitingConnection,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-connectionTimeout,90000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleConnections,30|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleTimeout,1800000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-validationTimeout,15000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-activeConnections,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-leakDetectionThreshold,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-maximumPoolSize,30|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-totalConnections,30",
"datatable_value": "8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-minimumIdle,10|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-threadsAwaitingConnection,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-connectionTimeout,30000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleConnections,10|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleTimeout,600000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-validationTimeout,5000|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-activeConnections,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-leakDetectionThreshold,0|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-maximumPoolSize,10|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-totalConnections,10",
"service_id": "c29uZ3M=.1",
"datatable_count": "8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-minimumIdle,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-threadsAwaitingConnection,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-connectionTimeout,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleConnections,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-idleTimeout,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-validationTimeout,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-activeConnections,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-leakDetectionThreshold,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-maximumPoolSize,3|8f4533b8-9761-4c49-b902-f88257c06d05_localhost:-1-totalConnections,3",
"time_bucket": 202310230003,
"entity_id": "c29uZ3M=.1_Mzg0ZWZlYWE2NzFjNGFhYjg2ZGFmZjA3OWE4YjljYzZAMTcyLjIyLjAuNg=="
}
}我们分别在6.8,7.10,8.8的集群上写入相同的数据,通过_stats/store,segments接口,我们得到三个版本的索引统计信息的区别:
版本
文档数量
存储大小
段数量
内存占用
6.8
1672526
273004812字节
2
43509字节
7.10
1672526
171867470字节
2
53304字节
8.8
1672526
157943758字节
2
0字节
从表格中可以看出,以下是一些主要的区别:
存储大小随着版本的升级而减少,8.8版本的存储大小是157943758字节,比6.8版本的存储大小减少了41.2%,比7.10版本的存储大小减少了8.2%。这说明8.8版本在文档压缩和索引优化方面有很大的改进,特别是当索引中含有比较多的keyword和数值类型字段时。
指标 6.8指标 7.10指标 8.8总结Elasticsearch 是一个强大的分布式搜索和分析引擎,它可以帮助用户快速地处理海量的日志数据,并从中发现有价值的洞察。随着 Elasticsearch 的不断更新和优化,它在日志分析场景中的表现也越来越出色,无论是在存储空间、查询效率还是分析功能方面,都有着显著的提升。本文通过对比 Elasticsearch 的三个版本(6.8、7.10和8.8)在同样数据上的索引大小,展示了它们在日志分析场景中存储成本差异。
在测试结果中,我们可以看到,在未经过任何优化的情况下:
日志场景中,相对于6.8版本,8.8版本的存储优化百分比约为14.78%。相对于7.10版本,8.8版本的存储优化百分比约为12.64%。从6.8版本到7.10版本,内存占用大幅减少,而到了8.8版本则为0。这是因为Elasticsearch对内存管理进行了改进,采用了堆外内存加载的方式。在指标数据方面,8.8版本,比6.8版本减少了41.2%,比7.10版本减少了8.2%。这表明8.8版本在文档压缩和索引优化方面有了显著的改进,尤其是在索引中包含大量关键字和数值类型字段时。 (请注意,以上结果仅针对当前测试数据,实际结果可能会因环境和数据特征而有所不同)
我们希望本文能够帮助用户更好地了解最新版本 Elasticsearch 的优势和潜力,并在选择技术时做出更明智的决策。如果你对本文的内容有任何疑问或建议,欢迎在评论区留言,我们将尽快回复你。同时,也请继续关注我们这一系列主题的文章。
感谢你的阅读和支持!