Оптимизация запросов типа Elasticsearch - PullRequest
0 голосов
/ 16 января 2019

В настоящее время я работаю над поддержкой typeahead (с содержит, а не только начинается с) для более 100 000 000 записей (и это число может произвольно расти) с использованием ElasticSearch. Текущая настройка работает, но мне было интересно, есть ли лучший подход к ней.

Я использую AWS Elasticsearch, поэтому у меня нет полного контроля над кластером.

Мой индекс определяется следующим образом:

{
"settings": {
    "analysis": {
        "analyzer": {
            "ngram_analyzer": {
                "tokenizer": "ngram_tokenizer",
                "filter": [
                    "lowercase"
                ]
            },
            "edge_ngram_analyzer": {
                "tokenizer": "edge_ngram_tokenizer",
                "filter": "lowercase"
            },
            "search_analyzer": {
                "tokenizer": "keyword",
                "filter": [
                    "lowercase"
                ]
            }
        },
        "tokenizer": {
            "ngram_tokenizer": {
                "type": "ngram",
                "min_gram": 3,
                "max_gram": 300,
                "token_chars": [
                    "letter",
                    "digit",
                    "symbol",
                    "punctuation",
                    "whitespace"
                ]
            },
            "edge_ngram_tokenizer": {
                "type": "edge_ngram",
                "min_gram": 3,
                "max_gram": 300,
                "token_chars": [
                        "letter",
                        "digit",
                        "symbol",
                        "punctuation",
                        "whitespace"
                    ]
            }
        }
    }
},
"mappings": {
    "account": {
        "properties": {
            "tags": {
                "type": "text",
                "analyzer": "ngram_analyzer",
                "search_analyzer": "search_analyzer"
            },
            "tags_prefix": {
                "type": "text",
                "analyzer": "edge_ngram_analyzer",
                "search_analyzer": "search_analyzer"
            },
            "tenantId": {
                "type": "text",
                "analyzer": "keyword"
            },
            "referenceId": {
                "type": "text",
                "analyzer": "keyword"
            }
        }
    }
}
}

Структура документов:

{
   "tenantId": "1234",
   "name": "A NAME",
   "referenceId": "1234567",
   "tags": [
       "1234567",
       "A NAME"
   ],
   "tags_prefix": [
       "1234567",
       "A NAME"
   ]
}

Смысл структуры состоит в том, что в документах есть доступные для поиска поля , над которыми работает заголовок, это не все в документе, так что это могут быть вещи даже в самом документе.

Поисковый запрос:

{
  "from": 0,
  "size": 10,
  "highlight": {
      "fields": {
          "tags": {}
      }
  },
  "query": {
      "bool": {
          "must": {
              "multi_match": {
                  "query": "a nam",
                  "fields": ["tags_prefix^100", "tags"]
              }
          },
          "filter": {
              "term": {
                  "tenantId": "1234"
              }
          }
      }
  }
}

Я делаю multi_match , потому что, хотя мне нужно напечатать, результаты, которые имеют совпадение в начале, должны возвращаться первыми, поэтому я следовал рекомендации в здесь

Текущая настройка: 10 осколков, 3 главных узла (t2.mediums), 2 узла данных / загрузки (t2.mediums) с диском EBS по 35 ГБ на каждом, что, как я знаю, составляет крошечный с учетом окончательного варианта. потребности системы, но достаточно полезны для экспериментов. У меня вставлено ~ 6000000 записей, а время отклика с холодным кэшем составляет около 300 мс.

Мне было интересно, является ли это правильным подходом или есть какие-то оптимизации, которые я мог бы внедрить в индекс / запрос, чтобы сделать это более производительным?

1 Ответ

0 голосов
/ 16 января 2019

Во-первых, я думаю, что решение, которое вы создаете, является хорошим, и оптимизацию, которую вы ищете, следует рассматривать, только если у вас есть проблема с текущим решением, то есть запросы слишком медленные. Нет необходимости в до-зрелых оптимизациях.

Во-вторых, я думаю, что вам не нужно предоставлять теги_prefix в ваших документах. все, что вам нужно, это использовать edge_ngram_tokenizer в поле тегов, которое создаст нужные префиксные токены для поиска. Вы можете использовать несколько полей , чтобы иметь несколько токенизаторов для одного и того же поля тегов.

В-третьих, тщательно используйте настройки edge_ngram_tokenizer, особенно настройки min_gram и max_gram. причина в том, что слишком высокая max_gram будет: а. создать слишком много префиксных токенов, будет занимать слишком много места б. уменьшить скорость индексации, так как индексация занимает больше времени с. бесполезен - вы не ожидаете, что автозаполнение будет учитывать 300 символов префикса. лучшие настройки токенов max должны быть (на мой взгляд) в диапазоне максимум 10-20 символов (или даже меньше).

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...