Разница в производительности 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
}
Мой вопрос:
Между показателями:
db.test.ensureIndex( { "key": 1 } )
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,
}
ПРИМЕЧАНИЕ:
Если вы уже используете внешний ключ для своих документов, то это не имеет значения, так как коллекции будут иметь