我有以下映射
\n\n{\n "yellows" : {\n "aliases" : { },\n "mappings" : {\n "yellow" : {\n "properties" : {\n "ranges" : {\n "type" : "nested",\n "properties" : {\n "geometry" : {\n "type" : "geo_shape"\n },\n "id" : {\n "type" : "long"\n },\n "other1" : {\n "type" : "keyword"\n },\n "other2" : {\n "type" : "long"\n },\n "other3" : {\n "type" : "long"\n }\n }\n }\n ...\n } \n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n越大,查询就越慢size。例如
curl https://path/to/elastic/yellows/_search?_source_exclude=ranges&from=0&size=50\' --data-binary \'{"query":{"bool":{"must":[],"filter":{"bool":{"filter":[{"terms":{"...":["1"]}},{"terms":{"...":["..."]}}],"should":[]}}}},"sort":[{"...":{"order":"asc"}}]}\'\n# size 50 -> "took":71\n\ncurl https://path/to/elastic/yellows/_search?_source_exclude=ranges&from=0&size=100\' --data-binary \'{"query":{"bool":{"must":[],"filter":{"bool":{"filter":[{"terms":{"...":["1"]}},{"terms":{"...":["..."]}}],"should":[]}}}},"sort":[{"...":{"order":"asc"}}]}\'\n# size 100 -> "took":1421\nRun Code Online (Sandbox Code Playgroud)\n\n同时,size=0or的查询_source=false速度很快。例如
curl https://path/to/elastic/yellows/_search?_source_exclude=ranges&from=0&size=0\' --data-binary \'{"query":{"bool":{"must":[],"filter":{"bool":{"filter":[{"terms":{"...":["1"]}},{"terms":{"...":["..."]}}],"should":[]}}}},"sort":[{"...":{"order":"asc"}}]}\'\n# size 0 -> "took":32\n\ncurl https://path/to/elastic/yellows/_search?_source=false&from=0&size=100\' --data-binary \'{"query":{"bool":{"must":[],"filter":{"bool":{"filter":[{"terms":{"...":["1"]}},{"terms":{"...":["..."]}}],"should":[]}}}},"sort":[{"...":{"order":"asc"}}]}\'\n# _source=false -> "took":167\nRun Code Online (Sandbox Code Playgroud)\n\n这意味着检索_sources(即没有_souce=false或size=0)的查询速度较慢。此外,似乎检索到的文档中的范围越多,响应速度就越慢。I\xe2\x80\x99mwc -c在下面使用作为检索文档中有多少范围的代理度量。不是最好的措施,但应该足够了
curl https://path/to/elastic/yellows/_search?from=0&size=50\' --data-binary \'{"query":{"bool":{"must":[],"filter":{"bool":{"filter":[{"terms":{"...":["1"]}},{"terms":{"...":["..."]}}],"should":[]}}}},"sort":[{"...":{"order":"asc"}}]}\' | wc -c\n# 2.332.822\n\ncurl https://path/to/elastic/yellows/_search?from=50&size=50\' --data-binary \'{"query":{"bool":{"must":[],"filter":{"bool":{"filter":[{"terms":{"...":["1"]}},{"terms":{"...":["..."]}}],"should":[]}}}},"sort":[{"...":{"order":"asc"}}]}\' | wc -c\n# 38.591.502\nRun Code Online (Sandbox Code Playgroud)\n\n正如您所看到的,前 50 个的范围比前 100 个中的第二个 50 个要少得多。另外,请注意,在第一个代码段中,前 50 个的查询比第二个 50 个的查询快得多,即使它有_source_exclude=ranges。
在我看来,查询并不是瓶颈。事实上,用size=0或用的_source=false响应时间很小。所以我怀疑 \xe2\x80\x99 是范围是嵌套字段的事实,即使请求排除它们(即_source_exclude=ranges),Elastic 也会考虑它们。
有没有其他方法可以在不更改映射的情况下使查询更快,或者我应该更改映射以使范围不嵌套?
\n你是对的,查询不是瓶颈。您观察到的是请求的获取阶段的时间不断增长,而搜索保持不变且相当小。
Elasticsearch 大致分两个阶段执行搜索请求:Query 阶段和Fetch 阶段。
在查询阶段,ES 确定哪些文档与查询匹配,为此,它使用快速索引,这些索引很可能缓存在 RAM 中。
在获取阶段,它实际上从磁盘中获取它们并发回响应。(获取实际上是分布式的,因为匹配的文档可以位于集群的任何节点。)
现在让我们看看您提到的每种情况会发生什么。
size=0?curl https://path/to/elastic/yellows/_search?_source_exclude=ranges&from=0&size=0' \
--data-binary '{"query":{"bool":{"must":[],"filter":{"bool":{"filter":[{"terms":{"...":["1"]}},{"terms":{"...":["..."]}}],"should":[]}}}},"sort":[{"...":{"order":"asc"}}]}'
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您告诉 Elasticsearch 跳过获取阶段:它仅返回匹配文档的数量。它也不进行任何排序,因为不需要。
_source=false当我们有和时会发生什么size=100?curl https://path/to/elastic/yellows/_search?_source=false&from=0&size=100' \
--data-binary '{"query":{"bool":{"must":[],"filter":{"bool":{"filter":[{"terms":{"...":["1"]}},{"terms":{"...":["..."]}}],"should":[]}}}},"sort":[{"...":{"order":"asc"}}]}'
Run Code Online (Sandbox Code Playgroud)
_source=false告诉 Elasticsearch 不要从磁盘获取 JSON。它仅返回文档 ID,在本例中按所需顺序排序。排序也主要在内存中执行:
排序时,相关排序字段值会加载到内存中。这意味着每个分片应该有足够的内存来容纳它们。
这就是为什么这个查询也很快。
from=50&size=50?curl https://path/to/elastic/yellows/_search?from=50&size=50' \
--data-binary '{"query":{"bool":{"must":[],"filter":{"bool":{"filter":[{"terms":{"...":["1"]}},{"terms":{"...":["..."]}}],"should":[]}}}},"sort":[{"...":{"order":"asc"}}]}' | wc -c
Run Code Online (Sandbox Code Playgroud)
在这里,我们要求 Elasticsearch 跳过前 50 条记录并给出接下来的 50 条。正如您所测量的,响应约为 36MB,这相当多。前 50 条记录仅需要传输 2MB 的数据。
所发生的情况是,Elasticsearch 最终必须访问磁盘,而且还要通过网络发送大量数据(而不仅仅是几个 100KB)。这就是你的查询速度较慢的原因。1.5 秒传输约 36MB 的传输速度为 24MB/秒(200MBit/秒),这是光纤连接的虚拟极限。
确实,查询嵌套字段比普通字段慢,但在这种情况下,这不太可能是问题:从磁盘读取数据并通过网络发送数据才是问题。
以下是有关调整搜索速度的一些提示,特别是建议为文件系统缓存提供更多内存。
您已经发现可以使用 来从响应中排除某些数据_source_exclude=ranges。如果您仍然需要响应,但您只关心该ranges数组的子集,则可以inner_hits这样做。默认情况下,它将返回前 3 个匹配的嵌套子文档。
给出性能优化建议总是很困难,因为它很大程度上取决于数据结构、数据量和用例。识别瓶颈很重要;在你的情况下,我会首先检查磁盘读/写功能和网络。
为了识别查询本身的瓶颈,我建议查看Profile API。
希望有帮助!
| 归档时间: |
|
| 查看次数: |
3469 次 |
| 最近记录: |