WEBKT

Elasticsearch 优化秘籍:禁用 _source 字段与 stored_fields 的取舍之道

2 0 0 0

1. 什么是 _source 字段?为什么它如此重要?

2. 禁用 _source 的优点和缺点

2.1 禁用 _source 的优点

2.2 禁用 _source 的缺点

3. 如何禁用 _source?

4. stored_fields 登场:如何在禁用 _source 的同时保留关键字段?

4.1 什么是 stored_fields?

4.2 如何使用 stored_fields?

4.3 stored_fields 的优势

4.4 stored_fields 的局限性

5. 实践案例:如何根据业务场景选择?

5.1 场景一:日志分析

5.2 场景二:电商商品搜索

5.3 场景三:用户行为分析

6. stored_fields 的高级用法:与脚本结合

6.1 脚本计算字段

6.2 脚本动态更新字段

7. 总结与最佳实践

8. 扩展阅读

大家好,我是老码农!今天咱们聊聊 Elasticsearch (ES) 优化中一个挺有意思的话题:禁用 _source 字段。这玩意儿吧,就像一把双刃剑,用好了能大幅提升性能,用不好可能让你痛不欲生。同时,咱们也会探讨如何使用 stored_fields 来实现类似的功能,让你在性能和功能之间找到最佳平衡点。

1. 什么是 _source 字段?为什么它如此重要?

首先,咱们得搞清楚 _source 字段是啥。简单来说,_source 字段就是存储了你在索引文档时提交的原始 JSON 文档。这意味着,当你查询数据时,ES 可以直接从 _source 中提取所有字段的值,而无需单独存储每个字段。这就像一个万能的“备份”,方便你随时恢复原始数据。

_source 字段的重要性体现在以下几个方面:

  • 灵活性: 即使你没有在 mapping 中定义某个字段,只要它存在于 _source 中,你仍然可以查询到它。这对于数据模型经常变化的场景非常友好。
  • 数据完整性: 原始文档完整地保存在 ES 中,方便你进行数据审计、重新索引等操作。
  • 易于使用: 大部分情况下,你无需关心字段的存储方式,直接查询即可。ES 会自动从 _source 中提取数据。

2. 禁用 _source 的优点和缺点

既然 _source 字段这么好,那为什么还要禁用它呢?原因很简单:为了性能!

2.1 禁用 _source 的优点

  • 索引速度更快: 不存储 _source 字段,意味着 ES 在索引文档时需要写入的数据量减少了。这会显著提升索引速度,尤其是在文档比较大或者字段很多的情况下。
  • 存储空间更小: _source 字段会占用大量的存储空间。禁用它后,你可以节省大量的磁盘空间,降低存储成本。
  • 查询性能提升: 虽然听起来有点矛盾,但在某些情况下,禁用 _source 也能提升查询性能。例如,当你只需要查询少数几个字段时,ES 可以只加载这些字段的值,而无需解析整个 _source 字段。

2.2 禁用 _source 的缺点

  • 无法获取原始文档: 这是禁用 _source 的最大问题。一旦你禁用了它,你就无法通过 ES 直接获取原始的 JSON 文档。这会影响你的数据审计、重新索引等操作。
  • mapping 必须精确定义: 你必须在 mapping 中明确定义所有需要查询的字段。如果你忘记定义某个字段,或者数据中出现了 mapping 中未定义的字段,你将无法查询到它们。
  • 脚本和高亮功能受限: _source 字段是 ES 中很多脚本和高亮功能的基础。禁用它后,你可能无法使用这些功能,或者需要采用其他的实现方式。

3. 如何禁用 _source

禁用 _source 非常简单,只需要在创建 index 或者 mapping 时,将 _source 设置为 false 即可。以下是一个示例:

PUT /my_index
{
"mappings": {
"properties": {
"title": {
"type": "text"
},
"content": {
"type": "text"
}
},
"_source": {
"enabled": false
}
}
}

在这个例子中,我们创建了一个名为 my_index 的 index,并将 _source 设置为 false。这意味着,ES 将不会存储文档的原始 JSON 数据。

4. stored_fields 登场:如何在禁用 _source 的同时保留关键字段?

禁用 _source 虽然可以提升性能,但也带来了很多限制。那么,有没有一种方法可以既享受到禁用 _source 带来的好处,又能保留某些关键字段呢?答案是肯定的,那就是使用 stored_fields

4.1 什么是 stored_fields

stored_fields 允许你单独存储文档中的某些字段。这些字段会被存储在索引中,并且可以被查询和聚合,即使你禁用了 _source 字段。

4.2 如何使用 stored_fields

使用 stored_fields 也非常简单。在创建 mapping 时,你可以为每个字段设置 store 属性。如果将 store 设置为 true,则该字段的值会被存储在 stored_fields 中。以下是一个示例:

PUT /my_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"store": true
},
"content": {
"type": "text",
"store": false
},
"author": {
"type": "keyword",
"store": true
}
},
"_source": {
"enabled": false
}
}
}

在这个例子中,我们禁用了 _source 字段,并为 titleauthor 字段设置了 store: true。这意味着,ES 将会存储 titleauthor 字段的值,而不会存储 content 字段的值。

4.3 stored_fields 的优势

  • 选择性存储: 你可以根据需要,选择性地存储关键字段,而不是存储整个文档。
  • 性能优化: 相比于存储整个 _source 字段,存储少量关键字段可以显著提升索引和查询性能。
  • 数据安全: 你可以选择不存储敏感数据,从而提高数据安全性。

4.4 stored_fields 的局限性

  • 需要提前定义: 你必须在 mapping 中明确定义需要存储的字段。如果你忘记定义某个字段,或者数据中出现了 mapping 中未定义的字段,你将无法查询到它们。
  • 存储空间占用: 虽然 stored_fields 可以节省存储空间,但存储的字段越多,占用的空间也会越多。
  • 无法获取原始文档: 与禁用 _source 一样,你无法获取原始的 JSON 文档。这意味着你仍然需要考虑数据审计、重新索引等问题。

5. 实践案例:如何根据业务场景选择?

接下来,咱们结合一些实际的业务场景,来聊聊如何选择禁用 _source 和使用 stored_fields

5.1 场景一:日志分析

在日志分析场景中,通常需要存储大量的日志数据。日志的结构通常比较固定,但字段数量可能很多。在这种场景下,禁用 _source 是一个不错的选择。你可以只存储关键的字段,例如:timestamplevelmessage 等。这样既可以提升索引和查询性能,又能满足基本的分析需求。

  • 方案: 禁用 _source,使用 stored_fields 存储关键字段。对于 message 字段,可以考虑使用分词器进行全文检索,以便进行更灵活的分析。
  • 代码示例:
PUT /log_index
{
"mappings": {
"properties": {
"timestamp": {
"type": "date",
"store": true
},
"level": {
"type": "keyword",
"store": true
},
"message": {
"type": "text",
"store": false
}
},
"_source": {
"enabled": false
}
}
}

5.2 场景二:电商商品搜索

在电商商品搜索场景中,需要存储商品的信息,例如:titledescriptionpricecategory 等。用户通常需要根据这些字段进行搜索和筛选。在这种场景下,stored_fields 也可以发挥很大的作用。

  • 方案: 禁用 _source,使用 stored_fields 存储关键字段。例如,存储 titlepricecategory 等字段,用于搜索和筛选。对于 description 字段,可以使用全文检索,以便用户可以搜索商品的描述信息。
  • 代码示例:
PUT /product_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"store": true
},
"description": {
"type": "text",
"store": false
},
"price": {
"type": "float",
"store": true
},
"category": {
"type": "keyword",
"store": true
}
},
"_source": {
"enabled": false
}
}
}

5.3 场景三:用户行为分析

在用户行为分析场景中,需要存储用户的各种行为数据,例如:点击、浏览、购买等。这些数据通常包含大量的字段,而且结构可能经常变化。在这种场景下,是否禁用 _source 需要仔细权衡。

  • 方案一(禁用 _source): 如果你主要关注某些固定的指标,例如:用户访问次数、页面停留时间等,那么可以禁用 _source,并使用 stored_fields 存储这些关键指标。
  • 方案二(不禁用 _source): 如果你需要灵活地分析用户的行为数据,并且经常需要根据新的字段进行分析,那么建议不要禁用 _source。虽然索引和查询性能可能会受到影响,但你可以获得更高的灵活性。
  • 代码示例(方案一):
PUT /user_behavior_index
{
"mappings": {
"properties": {
"user_id": {
"type": "keyword",
"store": true
},
"event_type": {
"type": "keyword",
"store": true
},
"timestamp": {
"type": "date",
"store": true
},
"page_id": {
"type": "keyword",
"store": true
},
"duration": {
"type": "integer",
"store": true
}
},
"_source": {
"enabled": false
}
}
}

6. stored_fields 的高级用法:与脚本结合

除了基本的存储字段外,stored_fields 还可以与脚本结合,实现更强大的功能。

6.1 脚本计算字段

你可以使用脚本来计算 stored_fields 的值。例如,你可以根据用户的购买历史,计算用户的总消费金额,并将结果存储在 stored_fields 中。这可以简化查询操作,提高查询效率。

PUT /user_index/_mapping
{
"properties": {
"purchases": {
"type": "nested",
"properties": {
"amount": {
"type": "float"
}
}
},
"total_spent": {
"type": "float",
"script": {
"source": "double total = 0; for (item in params._source.purchases) { total += item.amount; } return total;",
"lang": "painless"
},
"store": true
}
}
}

在这个例子中,我们使用脚本计算了用户的总消费金额,并将结果存储在 total_spent 字段中。

6.2 脚本动态更新字段

你也可以使用脚本来动态更新 stored_fields 的值。例如,你可以根据用户的行为,更新用户的活跃度评分,并将结果存储在 stored_fields 中。

POST /user_index/_update/1
{
"script": {
"source": "ctx._source.active_score = ctx._source.active_score + params.increment;",
"lang": "painless",
"params": {
"increment": 10
}
}
}

在这个例子中,我们使用脚本动态更新了用户的活跃度评分。

7. 总结与最佳实践

禁用 _source 和使用 stored_fields 是一对非常强大的组合,可以帮助你在性能和功能之间找到最佳平衡点。下面是一些总结和最佳实践:

  • 评估你的需求: 在决定是否禁用 _source 之前,你需要仔细评估你的业务需求。考虑以下几个问题:
    • 你需要获取原始文档吗?
    • 你的数据模型是否稳定?
    • 你需要进行复杂的查询和聚合吗?
    • 性能是你的首要考虑因素吗?
  • 选择合适的方案: 根据你的需求,选择合适的方案。如果你的数据模型比较稳定,并且性能是首要考虑因素,那么可以禁用 _source,并使用 stored_fields 存储关键字段。如果你的数据模型经常变化,或者你需要进行复杂的查询和聚合,那么可能需要保留 _source
  • 精心设计 mapping: 在使用 stored_fields 时,你需要精心设计 mapping,明确定义需要存储的字段。确保你存储了所有需要查询和聚合的字段。
  • 测试你的方案: 在上线之前,你需要测试你的方案,确保它能够满足你的性能和功能需求。可以使用 Elasticsearch 的性能测试工具,例如:rally,来评估你的方案的性能。
  • 监控你的集群: 在上线之后,你需要监控你的 Elasticsearch 集群,确保它能够正常运行。监控指标包括:索引速度、查询速度、存储空间占用等。如果发现性能问题,你需要及时调整你的方案。

禁用 _source 和使用 stored_fields 是一门艺术,需要你根据实际的业务场景,灵活地运用。希望今天的分享能帮助你更好地优化你的 Elasticsearch 集群!

8. 扩展阅读

如果大家在实践过程中遇到任何问题,欢迎留言交流!


老码农 Elasticsearch_sourcestored_fields

评论点评

打赏赞助
sponsor

感谢您的支持让我们更好的前行

分享

QRcode

https://www.webkt.com/article/8238