2013-12-02 3 views
2

Я пытаюсь понять, как лучше всего работать с индексами в MongoDB. Допустим, что у меня есть набор документов, как этот:Индексы комплекса MongoDB

{ 
    _id:  1, 
    keywords: ["gap", "casual", "shorts", "oatmeal"], 
    age:  21, 
    brand:  "Gap", 
    color:  "Black", 
    gender: "female",  
    retailer: "Gap", 
    style:  "Casual Shorts", 
    student: false, 
    location: "US", 
} 

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

db.items.find({ age:  { $gt: 13, $lt: 40 }, 
       brand: { $in: ['Gap', 'Target'] }, 
       retailer: { $in: ['Gap', 'Target'] }, 
       gender: { $in: ['male', 'female'] }, 
       style: { $in: ['Casual Shorts', 'Jeans']}, 
       location: { $in: ['US', 'International'] }, 
       color: { $in: ['Black', 'Green'] }, 
       keywords: { $all: ['gap', 'casual'] } 
       }) 

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

db.items.ensureIndex({ age: 1, brand: 1, retailer: 1, gender: 1, style: 1, location: 1, color: 1, keywords: 1}) 

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

ответ

1

Должен ли я создать составной индекс, как это:

db.items.ensureIndex ({возраст: 1, бренд: 1, розничный торговец: 1, пол: 1, стиль: 1, расположение : 1, цвет: 1, ключевые слова: 1})

Вы можете создать индекс, подобный приведенному выше, но вы индексируете почти всю коллекцию. Индексы занимают пространство; чем больше полей в индексе, тем больше места используется. Обычно ОЗУ, хотя их можно поменять. Они также несут штраф за штраф.

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

Есть ли лучший набор индексов, которые я могу создать для оптимизации этого запроса?

Как я уже говорил, вероятно, да. Но этот вопрос очень трудно ответить, не зная подробностей коллекции, как и количество документов, которые у нее есть, какие значения могут иметь каждое поле, как эти значения распределяются в коллекции (50% мужчин-мужчин, 50% женщин-женщин?) , как они соотносятся друг с другом и т. д.

Существует несколько стратегий индексирования, но обычно вы должны стремиться создавать индексы с высокой избирательностью. Выберите «маленькие» комбинации полей, которые помогут MongoDB найти нужные документы, сканируя «разумное» количество из них. Опять же, «малые» и «разумные» будут зависеть от характеристик сбора и запроса, которые вы выполняете.

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

http://emptysqua.re/blog/optimizing-mongodb-compound-indexes/ http://docs.mongodb.org/manual/faq/indexes/#how-do-you-determine-what-fields-to-index http://docs.mongodb.org/manual/tutorial/create-queries-that-ensure-selectivity/

И использовать cursor.explain оценить свои индексы.

http://docs.mongodb.org/manual/reference/method/cursor.explain/

0

Большой индекс, подобный этому, будет наказывать вас за записи. Лучше всего индексировать то, что вам нужно, и пусть оптимист Mongo сделает большую часть работы за вас. Вы всегда можете указать give him an hint или, в крайнем случае, переиндексировать, если приложение или использование данных кардинально изменится.

Ваш запрос будет использовать индекс для полей с одним (быстрым) и использовать сканирование таблицы (медленное) на оставшихся документах.

В зависимости от вашего приложения несколько отдельных индексов могут быть лучше. Добавление большего количества индексов не улучшит производительность. С записью пенальти это может даже ухудшить (YMMV).

Вот основной алгоритм выбора полей поставить в индексе:

  • Что одно поле в запросе чаще всего?
  • Если это одно поле присутствует в запросе, сканирование таблицы будет дорогостоящим?
  • В каком другом поле можно указать индекс для дальнейшего сканирования таблицы?
+0

Давайте предположим, что я только добавить около 1000 документов в этой коллекции в день, и добавить их все в одном пакете во время простоя приложения, поэтому эффективно я никогда не пишу в коллекцию, только чтение из него. – TheDelChop

0

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

из the docs:

«Поскольку индекс„охватывает“запрос, MongoDB может и соответствовать условиям запроса и возвращает результаты, используя только индекс, MongoDB не нужно смотреть на документы, только индекс , чтобы выполнить запрос. Индекс также может охватывать операцию агрегационного конвейера в незащищенных коллекциях ».

Некоторые замечания:

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

  • Добавление индекса только в один или два из наиболее избирательных полей вашего запроса уже принесет очень значительный прирост производительности. Чем больше полей вы добавляете, тем больше размер индекса будет на диске.

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

+0

Построение индекса занимает несколько раз, что может быть неприемлемым при написании тяжелых приложений. Конечно, каталог (это то, как он выглядит) обычно не пишет тяжелый. – ixe013

+0

Правильно, @ ixe013 это приложение никоим образом не пишет. – TheDelChop