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 的优势和潜力,并在选择技术时做出更明智的决策。如果你对本文的内容有任何疑问或建议,欢迎在评论区留言,我们将尽快回复你。同时,也请继续关注我们这一系列主题的文章。

感谢你的阅读和支持!