スクリプト、キャッシュ、および検索速度
Elasticsearchは、スクリプトをできるだけ速く使用できるように、いくつかの最適化を行います。重要な最適化の1つはスクリプトキャッシュです。コンパイルされたスクリプトはキャッシュに置かれ、スクリプトを参照するリクエストはコンパイルペナルティを受けません。
キャッシュのサイズは重要です。スクリプトキャッシュは、ユーザーが同時にアクセスする必要があるすべてのスクリプトを保持できるだけの大きさであるべきです。
node statsでスクリプトキャッシュの排出が多く、コンパイルの数が増加している場合、キャッシュが小さすぎる可能性があります。
すべてのスクリプトはデフォルトでキャッシュされ、更新が発生したときのみ再コンパイルが必要です。デフォルトでは、スクリプトには時間ベースの有効期限はありません。この動作は、script.cache.expire
設定を使用して変更できます。script.cache.max_size
設定を使用してキャッシュのサイズを構成します。
スクリプトのサイズは65,535バイトに制限されています。script.max_size_in_bytes
の値を設定して、そのソフトリミットを増やします。スクリプトが非常に大きい場合は、ネイティブスクリプトエンジンの使用を検討してください。
検索速度の向上
スクリプトは非常に便利ですが、Elasticsearchのインデックス構造や関連する最適化を使用できません。この関係は、時には検索速度の低下を引き起こすことがあります。
インデックスデータを変換するためにスクリプトを頻繁に使用する場合、代わりにデータを取り込む際に変換することで検索を速くすることができます。ただし、それはしばしばインデックス速度の低下を意味します。検索速度を向上させる方法を示す実用的な例を見てみましょう。
検索を実行する際、2つの値の合計で結果をソートすることは一般的です。たとえば、テストスコアデータを含むインデックスmy_test_scores
を考えてみましょう。このインデックスには、long
型の2つのフィールドが含まれています:
math_score
verbal_score
これらの値を合計するスクリプトを使用してクエリを実行できます。このアプローチには問題はありませんが、スクリプトの評価がリクエストの一部として行われるため、クエリは遅くなります。次のリクエストは、grad_year
が2099
に等しいドキュメントを返し、スクリプトの評価によって結果をソートします。
Python
resp = client.search(
index="my_test_scores",
query={
"term": {
"grad_year": "2099"
}
},
sort=[
{
"_script": {
"type": "number",
"script": {
"source": "doc['math_score'].value + doc['verbal_score'].value"
},
"order": "desc"
}
}
],
)
print(resp)
Ruby
response = client.search(
index: 'my_test_scores',
body: {
query: {
term: {
grad_year: '2099'
}
},
sort: [
{
_script: {
type: 'number',
script: {
source: "doc['math_score'].value + doc['verbal_score'].value"
},
order: 'desc'
}
}
]
}
)
puts response
Js
const response = await client.search({
index: "my_test_scores",
query: {
term: {
grad_year: "2099",
},
},
sort: [
{
_script: {
type: "number",
script: {
source: "doc['math_score'].value + doc['verbal_score'].value",
},
order: "desc",
},
},
],
});
console.log(response);
コンソール
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_score
およびverbal_score
フィールドの値の合計を含めます。
Python
resp = client.indices.put_mapping(
index="my_test_scores",
properties={
"total_score": {
"type": "long"
}
},
)
print(resp)
Ruby
response = client.indices.put_mapping(
index: 'my_test_scores',
body: {
properties: {
total_score: {
type: 'long'
}
}
}
)
puts response
Js
const response = await client.indices.putMapping({
index: "my_test_scores",
properties: {
total_score: {
type: "long",
},
},
});
console.log(response);
コンソール
PUT /my_test_scores/_mapping
{
"properties": {
"total_score": {
"type": "long"
}
}
}
次に、インジェストパイプラインを使用して、math_score
とverbal_score
の合計を計算し、total_score
フィールドにインデックスします。
Python
resp = client.ingest.put_pipeline(
id="my_test_scores_pipeline",
description="Calculates the total test score",
processors=[
{
"script": {
"source": "ctx.total_score = (ctx.math_score + ctx.verbal_score)"
}
}
],
)
print(resp)
Ruby
response = client.ingest.put_pipeline(
id: 'my_test_scores_pipeline',
body: {
description: 'Calculates the total test score',
processors: [
{
script: {
source: 'ctx.total_score = (ctx.math_score + ctx.verbal_score)'
}
}
]
}
)
puts response
Js
const response = await client.ingest.putPipeline({
id: "my_test_scores_pipeline",
description: "Calculates the total test score",
processors: [
{
script: {
source: "ctx.total_score = (ctx.math_score + ctx.verbal_score)",
},
},
],
});
console.log(response);
コンソール
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
から新しいインデックスmy_test_scores_2
にドキュメントを再インデックスします。
Python
resp = client.reindex(
source={
"index": "my_test_scores"
},
dest={
"index": "my_test_scores_2",
"pipeline": "my_test_scores_pipeline"
},
)
print(resp)
Ruby
response = client.reindex(
body: {
source: {
index: 'my_test_scores'
},
dest: {
index: 'my_test_scores_2',
pipeline: 'my_test_scores_pipeline'
}
}
)
puts response
Js
const response = await client.reindex({
source: {
index: "my_test_scores",
},
dest: {
index: "my_test_scores_2",
pipeline: "my_test_scores_pipeline",
},
});
console.log(response);
コンソール
POST /_reindex
{
"source": {
"index": "my_test_scores"
},
"dest": {
"index": "my_test_scores_2",
"pipeline": "my_test_scores_pipeline"
}
}
パイプラインを使用して、my_test_scores_2
に新しいドキュメントをインデックスし続けます。
Python
resp = client.index(
index="my_test_scores_2",
pipeline="my_test_scores_pipeline",
document={
"student": "kimchy",
"grad_year": "2099",
"math_score": 1200,
"verbal_score": 800
},
)
print(resp)
Ruby
response = client.index(
index: 'my_test_scores_2',
pipeline: 'my_test_scores_pipeline',
body: {
student: 'kimchy',
grad_year: '2099',
math_score: 1200,
verbal_score: 800
}
)
puts response
Js
const response = await client.index({
index: "my_test_scores_2",
pipeline: "my_test_scores_pipeline",
document: {
student: "kimchy",
grad_year: "2099",
math_score: 1200,
verbal_score: 800,
},
});
console.log(response);
コンソール
POST /my_test_scores_2/_doc/?pipeline=my_test_scores_pipeline
{
"student": "kimchy",
"grad_year": "2099",
"math_score": 1200,
"verbal_score": 800
}
これらの変更はインデックスプロセスを遅くしますが、検索を速くすることができます。スクリプトを使用する代わりに、my_test_scores_2
で行われた検索をtotal_score
フィールドを使用してソートできます。応答はほぼリアルタイムです!このプロセスは取り込み時間を遅くしますが、検索時のクエリを大幅に増加させます。
Python
resp = client.search(
index="my_test_scores_2",
query={
"term": {
"grad_year": "2099"
}
},
sort=[
{
"total_score": {
"order": "desc"
}
}
],
)
print(resp)
Ruby
response = client.search(
index: 'my_test_scores_2',
body: {
query: {
term: {
grad_year: '2099'
}
},
sort: [
{
total_score: {
order: 'desc'
}
}
]
}
)
puts response
Js
const response = await client.search({
index: "my_test_scores_2",
query: {
term: {
grad_year: "2099",
},
},
sort: [
{
total_score: {
order: "desc",
},
},
],
});
console.log(response);
コンソール
GET /my_test_scores_2/_search
{
"query": {
"term": {
"grad_year": "2099"
}
},
"sort": [
{
"total_score": {
"order": "desc"
}
}
]
}