加载中

脚本、缓存和搜索速度

Elasticsearch 执行了许多优化措施,旨在尽可能加快脚本的使用速度。其中一个重要的优化是脚本缓存。编译后的脚本会被放入缓存中,以便引用该脚本的请求无需承担编译带来的性能损耗。

缓存大小至关重要。您的脚本缓存应该足够大,能够容纳用户需要并发访问的所有脚本。

如果您在 节点统计 (node stats) 中发现大量脚本缓存驱逐和不断增加的编译次数,则说明您的缓存可能太小了。

默认情况下,所有脚本都会被缓存,因此它们仅在更新时才需要重新编译。默认情况下,脚本没有基于时间的过期限制。您可以使用 script.cache.expire 设置来更改此行为。使用 script.cache.max_size 设置来配置缓存的大小。

注意

脚本的大小限制为 65,535 字节。设置 script.max_size_in_bytes 的值可以提高该软限制。如果您的脚本确实非常大,请考虑使用 原生脚本引擎 (native script engine)

脚本非常有用,但无法利用 Elasticsearch 的索引结构或相关的优化。这种局限性有时会导致搜索速度变慢。

如果您经常使用脚本来转换已索引的数据,则可以通过在摄取(ingest)过程中转换数据来提高搜索速度。然而,这通常意味着更慢的索引速度。让我们来看一个实际的例子,说明如何提高搜索速度。

在运行搜索时,根据两个值的总和对结果进行排序是很常见的。例如,考虑一个名为 my_test_scores 的索引,其中包含测试分数数据。该索引包含两个 long 类型的字段

  • math_score
  • verbal_score

您可以运行一个带有脚本的查询,将这些值相加。这种方法本身没有问题,但查询速度会变慢,因为脚本求值是作为请求的一部分进行的。以下请求返回 grad_year 等于 2099 的文档,并根据脚本的计算结果对结果进行排序。

				GET /my_test_scores/_search
					{
  "query": {
    "term": {
      "grad_year": "2099"
    }
  },
  "sort": [
    {
      "_script": {
        "type": "number",
        "script": {
          "source": "doc['math_score'].value + doc['verbal_score'].value"
        },
        "order": "desc"
      }
    }
  ]
}
		

如果您正在搜索小型索引,那么将脚本作为搜索查询的一部分可能是一个不错的解决方案。如果您想提高搜索速度,可以在摄取过程中执行此计算,并将总和索引到一个字段中。

首先,我们将向索引中添加一个名为 total_score 的新字段,其中将包含 math_scoreverbal_score 字段值的总和。

				PUT /my_test_scores/_mapping
					{
  "properties": {
    "total_score": {
      "type": "long"
    }
  }
}
		

接下来,使用包含 脚本处理器 (script processor)摄取管道 (ingest pipeline) 来计算 math_scoreverbal_score 的总和,并将其索引到 total_score 字段中。

				PUT _ingest/pipeline/my_test_scores_pipeline
					{
  "description": "Calculates the total test score",
  "processors": [
    {
      "script": {
        "source": "ctx.total_score = (ctx.math_score + ctx.verbal_score)"
      }
    }
  ]
}
		

要更新现有数据,请使用此管道将 my_test_scores 中的任何文档 重新索引 (reindex) 到一个名为 my_test_scores_2 的新索引中。

				POST /_reindex
					{
  "source": {
    "index": "my_test_scores"
  },
  "dest": {
    "index": "my_test_scores_2",
    "pipeline": "my_test_scores_pipeline"
  }
}
		

继续使用该管道将任何新文档索引到 my_test_scores_2 中。

				POST /my_test_scores_2/_doc/?pipeline=my_test_scores_pipeline
					{
  "student": "kimchy",
  "grad_year": "2099",
  "math_score": 1200,
  "verbal_score": 800
}
		

这些更改会减慢索引过程,但能实现更快的搜索。您无需使用脚本,而是可以使用 total_score 字段对 my_test_scores_2 的搜索进行排序。响应几乎是实时的!虽然此过程减慢了摄取时间,但它极大地提高了搜索时的查询速度。

				GET /my_test_scores_2/_search
					{
  "query": {
    "term": {
      "grad_year": "2099"
    }
  },
  "sort": [
    {
      "total_score": {
        "order": "desc"
      }
    }
  ]
}
		
© . This website operates independently and is not affiliated with or endorsed by Elasticsearch B.V. All brand names, logos, and trademarks are the property of their respective owners.