elasticsearch - ElasticSearch 搜索性能
问题描述
我正在开发一个类似于购物车的应用程序,我们在其中存储产品及其元数据 (JSON),我们期望更快的搜索结果。(预期的搜索结果应包含在产品 JSON 文档中任何位置具有搜索字符串的文档)
我们选择了 ElasticSearch(AWS 服务)来存储完整的产品 JSON。我们虽然这将有助于我们更快的搜索结果。
但是当我尝试测试我的搜索端点时,单个请求需要 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
更新:
我们每天收到多种产品的库存(具有不同productId
s 的单独 JSON),我们将它们存储在按日期索引的(例如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"
}
}
]
}
解决方案
您的弹性搜索查询存在几个问题。
将每天的产品存储在不同的索引中是您的设计选择,我不知道,但如果产品列表很小,那么它没有意义并且可能导致性能问题,因为现在这些产品将存储在不同的索引中较小的分片,这会增加您的搜索时间,而不是在单个分片中搜索它们,显然如果数据太大,那么拥有单个分片也会影响性能,但是您需要进行分析并相应地设计您的系统,我们可以提供帮助你在那。
现在让我们来看看您的查询,首先,您使用的是通配符查询,这无论如何都很慢,请阅读 Elasticsearch 的创始人自己评论的这篇文章 :-) 并且还提供了使用 n-gram 令牌而不是通配符的解决方案查询,我们也在生产中使用它来搜索部分术语。
您的查询的第三个问题是您
"all_fields": true,
在搜索查询中使用,它将在搜索期间包含索引中的所有字段,这是一项非常昂贵的事情,您应该只在搜索中包含相关字段。
我敢肯定,即使您不更改第一个(设计更改)但在查询中合并其他 2 个更改,它仍然会大大提高您的查询性能。
愉快的调试和学习。
推荐阅读
- reporting-services - 文本框中的 SSRS Mailto 表达式/超链接
- python - 无法在 VSCode 中安装 platformio
- sql - 如何使用 T-SQL 更新更改区分大小写的结果
- javascript - 使用 PDFKIT 和 Strapi (Koa) 将 pdf 管道传输到 http 响应
- android - 如何创建进度条作为imageview的边框
- javascript - 如何从音轨中获取 ArrayBuffer?
- django - 在Django模板中的for循环中对查询集进行排序不起作用
- javascript - 使用 face-api.js 包 (node.js) 时导入 @tensorflow/tfjs-node 的问题
- docker-compose - 没有得到 shinyproxy.log 保存在容器中
- json - Flutter 从 json 中获取数据而无需异步