Разница в производительности Mongodb между индексами Hash и Ascending (есть ли причина не использовать хэш в неупорядоченном поле?)

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

Я знаю, что вы не можете создать такой индекс: db.test.ensureIndex( { "key": "hashed", "sortOrder": 1 } ) потому что вы получаете ошибку

{
    "createdCollectionAutomatically" : true,
    "numIndexesBefore" : 1,
    "errmsg" : "exception: Currently only single field hashed index supported.",
    "code" : 16763,
    "ok" : 0
}

Мой вопрос:

Между показателями:

  1. db.test.ensureIndex( { "key": 1 } )

  2. db.test.ensureIndex( { "key": "hashed" } )

Для запроса db.products.find( { key: "a" } )какой из них более производительный? hashed ключ O(1)


Как я добрался до вопроса:

Прежде чем я знал, что вы не можете иметь многоключевые индексы с hashedЯ создал индекс формы db.test.ensureIndex( { "key": 1, "sortOrder": 1 } )и при его создании я задавался вопросом, был ли хешированный индекс более производительным, чем восходящий (хеш обычно O(1)). Я оставил ключ, как сейчас, потому что (как я уже говорил выше) db.test.ensureIndex( { "key": "hashed", "sortOrder": 1 } ) не было разрешено Но вопрос о том, быстрее ли хешируется индекс для поиска по ключу, остался в моей памяти.

Ситуация, в которой я сделал индекс, была:

У меня была коллекция, которая содержала отсортированный список документов, классифицированных по ключам.

например{key: a, sortOrder: 1, ...}, {key: a, sortOrder: 2, ...}, {key: a, sortOrder: 3, ...}, {key: b, sortOrder: 1, ...}, {key: b, sortOrder: 2, ...}...

Так как я использовал key чтобы классифицировать и sortOrder для разбивки на страницы, я всегда запрашивал фильтрацию с одним значением для key и используя sortOrder для заказа документов.

Это означает, что у меня было два возможных запроса:

  • Для первой страницы db.products.find( { key: "a" } ).limit(10).sort({"sortOrder", 1})
  • И для других страниц db.products.find( { key: "a" , sortOrder: { $gt: 10 } } ).limit(10).sort({"sortOrder", 1})

В этом конкретном сценарии поиск с O(1) для ключа и O(log(n)) для sortOrder было бы идеально, но это было запрещено.

2 ответа

Для запроса db.products.find( { key: "a" } )какой из них более производительный?

Учитывая это поле key индексируется в обоих случаях, сам поиск по индексу сложности будет очень похожим. Как значение a будет хешироваться и храниться в дереве индексов.

Если мы ищем общую стоимость производительности, хешированная версия потребует дополнительных (незначительных) затрат на хеширование значения a перед сопоставлением значения в дереве индекса. Смотрите также mongo / db / index / hash_access_method.h

Кроме того, хешированный индекс не сможет использовать сжатие префикса индекса (WiredTiger). Сжатие префикса индекса особенно эффективно для некоторых наборов данных, таких как наборы данных с низкой мощностью (например, страна), или наборов с повторяющимися значениями, таких как номера телефонов, коды социального обеспечения и гео-координаты. Это особенно эффективно для составных индексов, где первое поле повторяется со всеми уникальными значениями второго поля.

Есть ли причина не использовать хэш в неупорядоченном поле?

Как правило, нет причин хэшировать значение вне диапазона. Чтобы выбрать ключ шарда, учитывайте количество элементов, частоту и скорость изменения значения.

Хешированный индекс обычно используется для конкретного случая шардинга. Когда значение ключа шарда является монотонно увеличивающимся / убывающим значением, распределение данных, скорее всего, попадет только в один шард. Именно здесь хешированный ключ шарда сможет улучшить распределение записей. Это небольшой компромисс, чтобы значительно улучшить ваш кластер. Смотрите также Хешед против дальнего боя.

Стоит ли вставлять в документ случайный хеш или значение и использовать его для шардинга вместо хеша, сгенерированного в _id?

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

Преимущество использования встроенной хэш-функции заключается в том, что MongoDB автоматически вычисляет хэши при разрешении запросов с использованием хешированных индексов. Поэтому приложениям не нужно вычислять хэши.

При определенном типе использования индекс будет меньше!

Да! В очень конкретном сценарии, когда выполняются все три следующих условия.

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

Например, я создал два индекса, и для хешированной версии размер индекса был меньше. Это может привести к лучшему использованию памяти и диска.

      // The type of data in the collection. Each document is a random string with 65 characters.
{
  "myLargeRandomString": "40a9da87c3e22fe5c47392b0209f296529c01cea3fa35dc3ba2f3d04f1613f8e"
}

Индекс составляет около 1/4 от обычной версии!

      mongos> use MyDb
mongos> db.myCollection.stats()["indexSizes"]
{
    // A regular index. This one is sorted by the value of myLargeRandomString
    "myLargeRandomString_-1"     : 23074062336,

    // The hashed version of the index for the same field. It is around 1/4 of the original size.
    "myLargeRandomString_hashed" : 6557511680,
}

ПРИМЕЧАНИЕ:

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

Другие вопросы по тегам