読者です 読者をやめる 読者になる 読者になる

野次馬エンジニア道

野次馬な気持ちでプログラミングをあれこれと綴ります

ElasticSearch入門 (2) キャッシュ・検索

前回は基本概念をみたので続き。参考にした書籍が古すぎるので思い切って

Mastering Elasticsearch - Second Edition

Mastering Elasticsearch - Second Edition

で興味があったキャッシュと検索の動作を見てみた。Chapter 6. Low-level Index Controlが特に参考になる。

キャッシュ

フィルタキャッシュ

全文書(match_all)の中から"programming"のカテゴリにある文書を検索する例。この場合検索結果はキャッシュされる。 index.cache.filter.typenodeindexがある。デフォルトはnode。一番オーソドックスなキャッシュ。

GET books/_search
{
  "query": {"match_all": {}},
   "filter" : {
    "term" : {
     "category" : "programming"
    }
   }  
}

フィールドのキャッシュ

ElasticSearchはフィールドのデータを使うファセット、アグリゲーション、スクリプト実行やソートを行う際に データをメモリ上に一旦読み込む。I/OやCPU的にコストが高い処理なのでバージョンアップ毎にLuceneレベルでの改善が行われている。

その中の一つがインデキシングの際にインデックス毎にフィールドを"ディスクに"保存したDocValue*1

    "category" : {
     "type" : "string",
     "index" : "not_analyzed",
     "doc_values" : true
     }

で明示的にコントロール可能。

以前デフォルトだったfielddataはオンメモリなので、fielddataを使って出現頻度や正規表現を使ったフィルタも可能。例えば出現頻度で、50%以上のものだけに絞りこむ場合のクエリは

{
 "book" : {
  "properties" : {
   "tag" : {
    "type" : "string",
    "index" : "not_analyzed",
    "doc_values" : false,
    "fielddata" : {
     "filter" : {
      "frequency" : {
       "min" : 0.5,
       "max" : 0.99,
      }
     }
    }
   }
  }
 }
}

シャードレベルのクエリキャッシュ

settingsのところにある設定に注目。ElasticSearchはデフォルトでクラスタとして構築される。検索が行われると関連のあるシャードにクエリを投げる。その際のノードのローカルにキャッシュする設定。 1.4から導入*2されていてデフォルトは無効。

  "settings": {
    "index.cache.query.enable": true
  }

検索

ここまでの設定例で具体的に検索してみる。

インデックス作成

マッピングを作って

PUT books
{
 "settings" : {
  "number_of_shards" : 1,
  "number_of_replicas" : 0,
  "index.cache.query.enable": true
 },
 "mappings" : {
  "book" : {
   "properties" : {
    "category" : {
     "type" : "string",
     "index" : "not_analyzed",
     "doc_values" : false,
     "fielddata" : {
      "filter" : {
        "frequency" : {
        "min" : 0.5,
        "max" : 0.99
        }
      }
     }
    }
  }
 }
}

でバルクで投入

POST _bulk
{ "index": {"_index": "books", "_type": "book", "_id": "1"}}
{"category":["programming","algorithm"]}
{ "index": {"_index": "books", "_type": "book", "_id": "2"}}
{"category":["design pattern","architecture"]}
{ "index": {"_index": "books", "_type": "book", "_id": "3"}}
{"category":["programming","javascript"]}
{ "index": {"_index": "books", "_type": "book", "_id": "4"}}
{"category":["algorithm","statstics","programming"]}

"programming"を含む文書の例は、

GET books/_search
{
  "query": {"match_all": {}},
   "filter" : {
    "term" : {
     "category" : "programming"
    }
   }  
}

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 1,
    "hits": [
      {
        "_index": "books",
        "_type": "book",
        "_id": "1",
        "_score": 1,
        "_source": {
          "category": [
            "programming",
            "algorithm"
          ]
        }
      },
      {
        "_index": "books",
        "_type": "book",
        "_id": "3",
        "_score": 1,
        "_source": {
          "category": [
            "programming",
            "javascript"
          ]
        }
      },
      {
        "_index": "books",
        "_type": "book",
        "_id": "4",
        "_score": 1,
        "_source": {
          "category": [
            "algorithm",
            "statstics",
            "programming"
          ]
        }
      }
    ]
  }
}

"programming"を含む3文書がマッチ。続いてアグリゲーション。

GET books/_search
{
  "query" : {"match_all": {}},
  "aggregations" : {
    "filter" : {
      "terms" : {
        "field" : "category"
      }
    }
  }
}

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 1,
    "hits": [
      {
        "_index": "books",
        "_type": "book",
        "_id": "1",
        "_score": 1,
        "_source": {
          "category": [
            "programming",
            "algorithm"
          ]
        }
      },
      {
        "_index": "books",
        "_type": "book",
        "_id": "2",
        "_score": 1,
        "_source": {
          "category": [
            "design pattern",
            "architecture"
          ]
        }
      },
      {
        "_index": "books",
        "_type": "book",
        "_id": "3",
        "_score": 1,
        "_source": {
          "category": [
            "programming",
            "javascript"
          ]
        }
      },
      {
        "_index": "books",
        "_type": "book",
        "_id": "4",
        "_score": 1,
        "_source": {
          "category": [
            "algorithm",
            "statstics",
            "programming"
          ]
        }
      }
    ]
  },
  "aggregations": {
    "filter": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "programming",
          "doc_count": 3
        },
        {
          "key": "algorithm",
          "doc_count": 2
        }
      ]
    }
  }
}

50%以上なので集計の方は"programming"と”algorithm”だけになっていることがわかる。