Составные индексы MongoDB - имеет ли значение порядок сортировки? - PullRequest
0 голосов
/ 04 июля 2018

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

Допустим, у меня есть такая коллекция

{user_id:1,slug:'one-slug'}
{user_id:1,slug:'another-slug'}
{user_id:2,slug:'one-slug'}
{user_id:3,slug:'just-a-slug}

И я должен найти свою коллекцию, где

user id == 1 and slug == 'one-slug'

В этой коллекции слизни будут уникальными для идентификаторов пользователей. То есть пользовательский идентификатор 1 может иметь только одну порцию значения «one-slug».

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

Я немного прочитал, но не могу обернуть голову, особенно для моего сценария. Было бы здорово услышать от других.

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Вы можете представить однополевый индекс MongoDB как массив с указателями на местоположение документа. Например, если у вас есть коллекция с (обратите внимание, что последовательность намеренно вышла из строя):

[collection]
1: {a:3, b:2}
2: {a:1, b:2}
3: {a:2, b:1}
4: {a:1, b:1}
5: {a:2, b:2}

Индекс одного поля

Теперь, если вы делаете:

db.collection.createIndex({a:1})

Индекс выглядит примерно так:

[index a:1]
1: {a:1} --> 2, 4
2: {a:2} --> 3, 5
3: {a:3} --> 1

Обратите внимание на три важные вещи:

  • Сортируется по a по возрастанию
  • Каждая запись указывает на место, где находятся соответствующие документы
  • Индекс записывает только значения поля a. Поле b вообще не существует в индексе

Так что, если вы делаете запрос, как:

db.collection.find().sort({a:1})

Все, что нужно сделать, - это пройти индекс сверху вниз, извлечь и вывести документ, на который указывают записи. Обратите внимание, что вы также можете пройти индекс снизу, например ::1010 *

db.collection.find().sort({a:-1})

и единственная разница в том, что вы идете по указателю в обратном порядке.

Поскольку b вообще нет в индексе, вы не можете использовать индекс, когда запрашиваете что-либо о b.

Составной индекс

в составном индексе, например ::1010 *

db.collection.createIndex({a:1, b:1})

Это означает, что вы хотите сначала отсортировать по a, а затем по b. Индекс будет выглядеть так:

[index a:1, b:1]
1: {a:1, b:1} --> 4
2: {a:1, b:2} --> 2
3: {a:2, b:1} --> 3
4: {a:2, b:2} --> 5
5: {a:3, b:2} --> 1

Обратите внимание:

  • Индекс отсортирован по a
  • В каждом a у вас есть отсортированный b
  • У вас есть 5 записей индекса против только трех в предыдущем примере с одним полем

Используя этот индекс, вы можете сделать запрос вроде:

db.collection.find({a:2}).sort({b:1})

Он может легко найти, где a:2, а затем пройти указатель вперед. Учитывая этот индекс, вы не можете сделать :

db.collection.find().sort({b:1})
db.collection.find({b:1})

В обоих запросах вы не можете легко найти b, поскольку он распространяется по всему индексу (то есть не в смежных записях). Однако вы можете сделать:

db.collection.find({a:2}).sort({b:-1})

, поскольку вы можете найти, где находится a:2, и пройтись по b записям назад.

Редактировать : уточнение вопроса @ marcospgp в комментарии:

Возможность использования индекса {a:1, b:1} для удовлетворения find({a:2}).sort({b:-1}) действительно имеет смысл, если вы видите это с точки зрения отсортированной таблицы. Например, индекс {a:1, b:1} можно рассматривать как:

a | b
--|--
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2

найти ({а: 2}). Рода ({Ь: 1})

Индекс {a:1, b:1} означает sort by a, then within each a, sort the b values. Если вы затем выполните find({a:2}).sort({b:1}), индекс знает, где находятся все a=2. В пределах этого блока a=2, b будет отсортирован в порядке возрастания (согласно спецификации индекса), так что запрос find({a:2}).sort({b:1}) может быть удовлетворен:

a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block forward to satisfy
2 | 2 <-- find({a:2}).sort({b:1})
2 | 3 <--
3 | 1
3 | 2

найти ({а: 2}). Рода ({Ь: -1})

Поскольку указатель можно перемещать вперед или назад, была выполнена аналогичная процедура с небольшим поворотом в конце:

a | b
--|--
1 | 1
1 | 2
2 | 1  <-- walk this block backward to satisfy
2 | 2  <-- find({a:2}).sort({b:-1})
2 | 3  <--
3 | 1
3 | 2

Тот факт, что индекс может идти вперед или назад, является ключевым моментом, который позволяет запросу find({a:2}).sort({b:-1}) использовать индекс {a:1, b:1}.

Объяснение планировщика запросов

Вы можете увидеть, что планирует планировщик запросов, используя db.collection.explain().find(....). В основном, если вы видите stage из COLLSCAN, индекс не использовался или не может быть использован для запроса. См. объяснение результатов для получения подробной информации о выводе команды.

0 голосов
/ 04 июля 2018

[Нельзя комментировать из-за отсутствия репутации]

Направление индекса имеет значение только при сортировке.

Не совсем точно: некоторые запросы могут выполняться быстрее с определенным индексом направления, даже если в самом запросе не требуется порядок (сортировка только для результатов). Например, запросы с критериями даты: поиск пользователей, подписавшихся вчера, будет быстрее с направлением desc в индексе, чем с направлением asc или без индекса.

разница между {user_id: 1, slug: 1} и {slug: 1, user_id: 1}

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

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