検索対象シャードのスキップ
※ 備忘録がわりなので、読みやすくはありません。あしからず。
最初に
Elasticsearch 5.6から(?)、検索結果の表示にskipped
なる項目が。
こんな感じで普通に検索すると・・・
GET filebeat-*/_search
{
"size": 0,
"query": {
"range": {
"@timestamp": {
"gte": "2019-12-27"
}
}
}
}
結果は、こんな感じ。
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 0,
"max_score": 0,
"hits": []
}
}
skipped
って何だ?
じゃぁ、このskipped
って何でしょう。
Forumでもいろいろ話が出てますが、よくわかりません。
ただ、参考になる記述はあります。pre-filter
というキーワードが気になります。
実際に、コードのこのあたりを見てみると、それっぽい記述があります。
関連するのはpre_filter_shard_size
というパラメータ。
でも、このパラメータの記述はマニュアルにありません。このへんにあっても良さそうですが。
でも別のところには記述があります(6.6以降ですが・・・)。
Frozen Indexはデフォルトで検索対象とならないので、ignore_throttled=false
をつけて検索対象にしますが、そうすると折角メモリから追い出したのに、メモリに乗っけなきゃいけない=すんごい遅くなる、ので、なるべく検索対象になるシャードを減らす(読み込むファイルを減らす、かな?)ために、pre_filter_shard_size=1
を設定しましょう、と。
pre_filter_shard_size
を使ってみる
とりあえず、このパラメータを使って見ましょう。
GET filebeat-*/_search?pre_filter_shard_size=1
{
"size": 0,
"query": {
"range": {
"@timestamp": {
"gte": "2019-12-27"
}
}
}
}
すると、こんな感じに。
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 4,
"failed": 0
},
"hits": {
"total": 0,
"max_score": 0,
"hits": []
}
}
お、skipped
が出ますね。
この例だと、2018-12-27以降のデータのみ検索対象としたRangeクエりなわけですが、pre-filter phase(pre-flight search phase)でフィルタリングしてます。その時にスキップされたシャード数が4個だと。
6.6になって、Frozen IndexやIndex Lifecycle Management(ILM)が使えるようになると、徐々に認知されてくるんでしょうかねぇ・・・
注意点
てほどのことはないですが・・・
pre_filter_shard_size
のデフォルトは128なので、このパラメータを指定しない場合は129個以上のシャードが検索対象にならない限りはpre-filter phaseは発生しません。
検索対象シャード数がpre_filter_shard_size
の値を超える場合は必ずpre-filter phaseは発生しますが、時間指定のRangeクエリ以外ではスキップは行われないようなので、常に指定していても良いというわけではなさそうです。
通常は、query phaseがあって、そこで必要なシャードが絞られてから、fetch phaseで実際のデータが取得されます。
pre-filter phaseはquery phaseの前に実行されるので、都合3回のリクエストがcoordinator nodeからdata nodeに送られることになります。なので、時間指定のRangeクエリ以外に対してpre-filter phaseが発生するのは、オーバーヘッドが少ないphaseとはいえ避けられるなら避けたほうが良いと。