【问题标题】:How to identify expensive queries by the Query DSL?如何通过 Query DSL 识别昂贵的查询?
【发布时间】:2022-11-10 21:12:10
【问题描述】:

我的应用程序中有一个要求:识别应用程序中昂贵的弹性搜索查询。

我只知道弹性搜索有 Query DSL。 (https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html

我需要在elasticsearch的反向代理中识别每个elasticsearch查询(反向代理是用java开发的,只是为了限制对ES的请求并做一些用户统计),如果它是昂贵的查询,只有有限的用户才能以特定的速率执行限制。

对我来说困难的是如何识别昂贵的查询。我知道弹性搜索有一个开关,可以通过设置这个参数来禁用/启用昂贵的查询。我阅读了弹性搜索源代码,但我找不到弹性搜索如何识别不同类型的昂贵查询。

如果你知道的话:

  1. 是否有任何可以识别昂贵查询的 elasticsearch API(来自 elasticsearch 客户端 sdk)?然后我可以直接在我的应用程序中调用 API。
  2. 如果没有,您知道通过分析查询正文来识别昂贵查询的有效方法是什么吗?通过一些 AST(抽象语法树)解析器?还是通过在查询正文中搜索特定关键字?

    我真的很感激这方面的一些帮助!

【问题讨论】:

    标签: java json elasticsearch abstract-syntax-tree


    【解决方案1】:

    在 Elasticsearch 中没有一个很好的“原生”方法,但您确实有一些可能会有所帮助的选项

    设置 timeout 或 terminate_after

    此选项从不同的角度看待您的需求。

    来自 Elasticsearch 文档:search-your-data

    您可以通过查看结果中返回的took 字段来保存用户执行的每个查询所用时间的记录。

    {
      "took": 5,
      "timed_out": false,
    ...
    }
    

    这样,您就可以记录用户在“扩展”的时间窗口中执行了多少次查询(比 X 多)。

    对于该用户,您可以开始添加将尝试限制查询执行的timeoutterminate_after 参数。这不会阻止用户执行扩展查询,但它会在“超时”到期后尝试取消长时间运行的查询,将部分或空的结果返回给用户。

    GET /my-index-000001/_search
    {
      "timeout": "2s",
      "query": {
        "match": {
          "user.id": "kimchy"
        }
      }
    }
    

    这将限制该用户执行的扩展查询对集群的影响。

    旁注; this stackoverflow 回答指出,某些查询仍然可以绕过 timeout/terminate_after 标志,例如 script

    terminate_after 限制在每个分片上搜索的文档数量,这可能是一个可供使用的替代选项,如果超时太高或由于某种原因被忽略,甚至是另一个备份。

    长期分析

    这个答案可能需要更多的工作,但您可以保存有关执行的查询的统计信息以及它们所花费的时间。

    在这种情况下,您可能应该使用 queryDSL 的 json 表示,将它们保存在弹性搜索索引中,沿着查询所用的时间,并保留类似查询所用平均时间的聚合。

    您可以使用rollup 功能预先聚合所有平均值,并检查针对该索引的查询(如果它是“可能扩展的查询”)。

    这里的问题是要保存查询的哪一部分以及哪些查询“相似”到足以被考虑用于此聚合。

    在查询中搜索关键字

    您也将此作为一种选择。最后的 DSL 查询转换为带有 JSON 主体的 REST 调用,因此使用 JsonNode 您可以查找您“认为”将使查询扩展甚至限制诸如“桶数量”等的特定子元素。

    使用 ObjectMapper,您可以将查询写入字符串并查找关键字,这将是最简单的解决方案。

    我们知道有一些特定的功能需要 Elasticsearch 提供大量资源,并且可能需要很长时间才能完成,因此作为“第一道防线”,可以通过这个答案来限制这些功能。

    例子: 突出显示 脚本 搜索分析器 ETC...

    因此,尽管这个答案是最幼稚的,但当您处理需要分析的长期解决方案时,它可能是一个快速的胜利。

    【讨论】:

    • 非常感谢您的快速回复迪玛!并为我迟到的回复感到抱歉。
    • 我通过查找关键字实现了一个昂贵的查询识别器,有时它还需要考虑关键字的顺序和 json 正文中的一些基本/根元素。现在它看起来很好并且可以工作。感谢您的建议,让我知道这是一个快速但不好的解决方案。我也这么认为,这个解决方案也可能导致性能问题,因为我的反向代理流量很大。我真的认为解决方案 1 和 2 非常有价值,通过设置超时和一些长期分析,我将尽我所能在未来实施它们。
    【解决方案2】:

    除了 Dima 给出的一些很好的回答之外,这里是昂贵/慢查询的常见嫌疑人列表:https://blog.bigdataboutique.com/2022/10/expensive-queries-in-elasticsearch-and-opensearch-a83194

    一般来说,我们会将讨论分为三部分:

    1. 这是不是很慢的查询?有关常见嫌疑人,请参阅上面的列表。顺便说一句,可以通过在集群设置中将search.allow_expensive_queries 设置为false 来禁用其中一些。
    2. 或者它是一个聚合请求?
    3. 也许是集群不堪重负导致查询变慢,而不是实际查询。

      解决这个问题的唯一方法是查看一段时间内的集群指标,并与慢查询相关联。您还可以收集所有查询并分析它们以找出可疑的罪魁祸首,并与它们的延迟相关联。通常这会突出一些可以改进的东西(例如更好地使用缓存等)。

    【讨论】:

      猜你喜欢
      • 2017-12-23
      • 1970-01-01
      • 2015-06-11
      • 1970-01-01
      • 2010-09-20
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2020-12-23
      相关资源
      最近更新 更多