ElasticSearch 搜索性能
ElasticSearch search performance
我正在开发一个类似于某些购物车的应用程序,我们在其中存储产品及其元数据 (JSON),并且我们期待更快的搜索结果。 (预期的搜索结果应包含产品 JSON 文档中任何位置具有搜索字符串的文档)
我们选择了 ElasticSearch(AWS 服务)来存储完整的产品 JSONs。我们认为这有助于我们更快地获得搜索结果。
但是当我尝试测试我的搜索端点时,单个请求需要 2 秒以上,如果我使用 Jmeter 发出 100 个并行请求,它会持续增加到 30 秒。 (这些查询时间来自应用程序日志,而不是来自 Jmeter 响应。)
这是我存储在 ElasticSearch 中的示例产品 JSON 和示例搜索字符串。
我认为我们使用 ES 的方式不对,请帮助我们以正确的方式实现它。
产品JSON:
{
"dealerId": "D320",
"modified": 1562827907,
"store": "S1000",
"productId": "12345689",
"Items": [
{
"Manufacturer": "ABC",
"CODE": "V22222",
"category": "Electronics",
"itemKey": "b40a0e332190ec470",
"created": 1562828756,
"createdBy": "admin",
"metadata": {
"mfdDate": 1552828756,
"expiry": 1572828756,
"description": "any description goes here.. ",
"dealerName": "KrishnaKanth Sing, Bhopal"
}
}
]
}
搜索字符串:
krishna
更新:
我们每天收到包含多种产品的库存(不同的 JSON 和不同的 productId
),我们将它们存储在日期索引中(例如 products_20190715
)。
在搜索时,我们正在搜索 products_*
个索引。
我们正在使用 JestClient
库从我们的 SpringBoot
应用程序与 ES 通信。
示例搜索查询:
{
"query": {
"bool": {
"must": [
{
"bool": {
"must": [
{
"simple_query_string": {
"query": "krishna*",
"flags": -1,
"default_operator": "or",
"lenient": true,
"analyze_wildcard": false,
"all_fields": true,
"boost": 1
}
}
],
"disable_coord": false,
"adjust_pure_negative": true,
"boost": 1
}
}
],
"filter": [
{
"bool": {
"must": [
{
"bool": {
"should": [
{
"match_phrase": {
"category": {
"query": "Electronics",
"slop": 0,
"boost": 1
}
}
},
{
"match_phrase": {
"category": {
"query": "Furniture",
"slop": 0,
"boost": 1
}
}
},
{
"match_phrase": {
"category": {
"query": "Sports",
"slop": 0,
"boost": 1
}
}
}
],
"disable_coord": false,
"adjust_pure_negative": true,
"boost": 1
}
}
],
"disable_coord": false,
"adjust_pure_negative": true,
"boost": 1
}
},
{
"bool": {
"disable_coord": false,
"adjust_pure_negative": true,
"boost": 1
}
}
],
"disable_coord": false,
"adjust_pure_negative": true,
"boost": 1
}
},
"sort": [
{
"modified": {
"order": "desc"
}
}
]
}
使用 Post 处理器 JSON 提取器并获取您需要输入的数据模式作为搜索字符串。
给出 JSON 表达式和匹配数为 0 以随机获取模式,1 表示第一个数据,2nd 表示第二个数据,依此类推。因此,您已使搜索字符串动态化。
这将复制真实场景,因为每个用户都不会搜索相同的字符串。
当您在服务器上放置更多 sequential/concurrent 用户时,从每个请求获得响应的时间逐渐增加是正常的。但您需要关注的是服务器故障和摘要报告中请求的平均时间。
一般来说,作为标准,请求的响应时间不应超过 10 秒。(取决于公司和产品类型)。请注意,Jmeter 的默认超时时间约为 21 seconds.If,请求时间超过此时间,它会自动失败(如果 "Delay thread creation until needed" 在线程组中被禁用)。但是您可以在Jmeter中的每个请求的高级选项卡中断言期望值。
您的 elasticsearch 查询有几个问题。
将每天的产品存储在不同的索引中是您的设计选择,我不知道这一点,但如果它的产品列表很小,那么它就没有意义并且可能会导致性能问题,因为现在这些产品将存储在 不同的较小分片 中,这会增加您的搜索时间,而不是在单个分片中搜索它们,显然,如果数据太大,那么使用单个分片将也会影响性能,但您需要进行分析并相应地设计您的系统,我们可以在这方面为您提供帮助。
现在开始您的查询,首先,您使用的是通配符查询,它无论如何都很慢,请阅读这篇 post Elasticsearch 创始人自己评论的文章 :-) 以及还提供了使用 n-grams 标记而不是通配符查询的解决方案,我们也在生产中使用它来搜索部分术语。
您的查询的第三个问题是您在搜索查询中使用了 "all_fields": true,
,这将包括搜索期间索引中的所有字段,这相当这是一件代价高昂的事情,您应该只在搜索中包含相关字段。
我敢肯定,即使您不更改第一个(设计更改)但将其他两个更改合并到您的查询中,它仍然会大大提高您的查询性能。
调试和学习愉快。
我正在开发一个类似于某些购物车的应用程序,我们在其中存储产品及其元数据 (JSON),并且我们期待更快的搜索结果。 (预期的搜索结果应包含产品 JSON 文档中任何位置具有搜索字符串的文档)
我们选择了 ElasticSearch(AWS 服务)来存储完整的产品 JSONs。我们认为这有助于我们更快地获得搜索结果。
但是当我尝试测试我的搜索端点时,单个请求需要 2 秒以上,如果我使用 Jmeter 发出 100 个并行请求,它会持续增加到 30 秒。 (这些查询时间来自应用程序日志,而不是来自 Jmeter 响应。)
这是我存储在 ElasticSearch 中的示例产品 JSON 和示例搜索字符串。
我认为我们使用 ES 的方式不对,请帮助我们以正确的方式实现它。
产品JSON:
{
"dealerId": "D320",
"modified": 1562827907,
"store": "S1000",
"productId": "12345689",
"Items": [
{
"Manufacturer": "ABC",
"CODE": "V22222",
"category": "Electronics",
"itemKey": "b40a0e332190ec470",
"created": 1562828756,
"createdBy": "admin",
"metadata": {
"mfdDate": 1552828756,
"expiry": 1572828756,
"description": "any description goes here.. ",
"dealerName": "KrishnaKanth Sing, Bhopal"
}
}
]
}
搜索字符串:
krishna
更新:
我们每天收到包含多种产品的库存(不同的 JSON 和不同的 productId
),我们将它们存储在日期索引中(例如 products_20190715
)。
在搜索时,我们正在搜索 products_*
个索引。
我们正在使用 JestClient
库从我们的 SpringBoot
应用程序与 ES 通信。
示例搜索查询:
{
"query": {
"bool": {
"must": [
{
"bool": {
"must": [
{
"simple_query_string": {
"query": "krishna*",
"flags": -1,
"default_operator": "or",
"lenient": true,
"analyze_wildcard": false,
"all_fields": true,
"boost": 1
}
}
],
"disable_coord": false,
"adjust_pure_negative": true,
"boost": 1
}
}
],
"filter": [
{
"bool": {
"must": [
{
"bool": {
"should": [
{
"match_phrase": {
"category": {
"query": "Electronics",
"slop": 0,
"boost": 1
}
}
},
{
"match_phrase": {
"category": {
"query": "Furniture",
"slop": 0,
"boost": 1
}
}
},
{
"match_phrase": {
"category": {
"query": "Sports",
"slop": 0,
"boost": 1
}
}
}
],
"disable_coord": false,
"adjust_pure_negative": true,
"boost": 1
}
}
],
"disable_coord": false,
"adjust_pure_negative": true,
"boost": 1
}
},
{
"bool": {
"disable_coord": false,
"adjust_pure_negative": true,
"boost": 1
}
}
],
"disable_coord": false,
"adjust_pure_negative": true,
"boost": 1
}
},
"sort": [
{
"modified": {
"order": "desc"
}
}
]
}
使用 Post 处理器 JSON 提取器并获取您需要输入的数据模式作为搜索字符串。
给出 JSON 表达式和匹配数为 0 以随机获取模式,1 表示第一个数据,2nd 表示第二个数据,依此类推。因此,您已使搜索字符串动态化。 这将复制真实场景,因为每个用户都不会搜索相同的字符串。
当您在服务器上放置更多 sequential/concurrent 用户时,从每个请求获得响应的时间逐渐增加是正常的。但您需要关注的是服务器故障和摘要报告中请求的平均时间。
一般来说,作为标准,请求的响应时间不应超过 10 秒。(取决于公司和产品类型)。请注意,Jmeter 的默认超时时间约为 21 seconds.If,请求时间超过此时间,它会自动失败(如果 "Delay thread creation until needed" 在线程组中被禁用)。但是您可以在Jmeter中的每个请求的高级选项卡中断言期望值。
您的 elasticsearch 查询有几个问题。
将每天的产品存储在不同的索引中是您的设计选择,我不知道这一点,但如果它的产品列表很小,那么它就没有意义并且可能会导致性能问题,因为现在这些产品将存储在 不同的较小分片 中,这会增加您的搜索时间,而不是在单个分片中搜索它们,显然,如果数据太大,那么使用单个分片将也会影响性能,但您需要进行分析并相应地设计您的系统,我们可以在这方面为您提供帮助。
现在开始您的查询,首先,您使用的是通配符查询,它无论如何都很慢,请阅读这篇 post Elasticsearch 创始人自己评论的文章 :-) 以及还提供了使用 n-grams 标记而不是通配符查询的解决方案,我们也在生产中使用它来搜索部分术语。
您的查询的第三个问题是您在搜索查询中使用了
"all_fields": true,
,这将包括搜索期间索引中的所有字段,这相当这是一件代价高昂的事情,您应该只在搜索中包含相关字段。
我敢肯定,即使您不更改第一个(设计更改)但将其他两个更改合并到您的查询中,它仍然会大大提高您的查询性能。
调试和学习愉快。