2013-11-29 3 views
1

Я создал 4 индекса для проверки производительности запросов в моей коллекции при запросе на два поля одного и того же документа, одним из которых является массив (требуется многокнопочный индекс). Два индекса - одно и два соединения.Почему один индекс быстрее, чем составной индекс в запросе для двух ключей? (MongoDB, multi-key)

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

Это мои показатели:

{ "v" : 1, 
    "key" : { "_id" : 1 }, 
    "ns" : "bt_twitter.mallorca.mallorca", 
    "name" : "_id_" 
}, 
{ "v" : 1, 
    "key" : { "epoch_creation_date" :1 }, 
    "ns" : "bt_twitter.mallorca.mallorca", 
    "name" : "epoch_creation_date_1" 
}, 
{  "v" : 1, 
     "key" : { "related_hashtags" : 1 }, 
     "ns" : "bt_twitter.mallorca.mallorca", 
     "name" : "related_hashtags_1" 
}, 
{  "v" : 1, 
     "key" : { "epoch_creation_date" : 1, "related_hashtags" : 1 }, 
     "ns" : "bt_twitter.mallorca.mallorca", 
     "name" : "epoch_creation_date_1_related_hashtags_1" 
} 

Моих запросы и показатели эффективности (параметр подсказки показывает индекс, используемый при каждом запросе):

Запрос 1:

active_collection.find(
    {'epoch_creation_date': {'$exists': True}}, 
    {"_id": 0, "related_hashtags":1} 
).hint([("epoch_creation_date", ASCENDING)]).explain() 

Миллис: 237

nscanned: 101226

QUERY 2:

active_collection.find(
    {'epoch_creation_date': {'$exists': True}}, 
    {"_id": 0, "related_hashtags": 1} 
).hint([("related_hashtags", ASCENDING)]).explain() 

Миллис: 1131

nscanned: 306715

QUERY 3:

active_collection.find(
    {'epoch_creation_date': {'$exists': True}}, 
    {"_id": 0, "related_hashtags": 1} 
).hint([("epoch_creation_date", ASCENDING), ("related_hashtags", ASCENDING)]).explain() 

Миллис: 935

nscanned: 306715

QUERY 4:

active_collection.find(
    {'epoch_creation_date': {'$exists': True}}, 
    {"_id": 0, "related_hashtags": 1} 
).hint([("related_hashtags", ASCENDING),("epoch_creation_date", ASCENDING)]).explain() 

Миллис: 1165

nscanned: 306715

QUERY 1 просматривает меньше документов, что, вероятно, причина, чтобы быть быстрее. Может ли кто-нибудь помочь мне понять, почему он работает лучше, чем запросы с составными индексами? Поэтому, когда лучше использовать составной индекс, чем один?

Я читаю документацию mongo, но эти концепции приводят к трудным для меня перевариванию.

Заранее спасибо.

ОБНОВЛЕНО вопрос (в ответ на Sammaye и Philipp)

Это является результатом полного объяснения()

"cursor" : "BtreeCursor epoch_creation_date_1", 
"isMultiKey" : false, 
"n" : 101226, 
"nscannedObjects" : 101226, 
"nscanned" : 101226, 
"nscannedObjectsAllPlans" : 101226, 
"nscannedAllPlans" : 101226, 
"scanAndOrder" : false, 
"indexOnly" : false, 
"nYields" : 0, 
"nChunkSkips" : 0, 
"millis" : 242, 
"indexBounds" : {u'epoch_creation_date': [[{u'$minElement': 1}, {u'$maxElement': 1}]] 

}, 
"server" : "vmmongodb:27017" 

для следующего запроса:

active_collection.find(
{'epoch_creation_date': {'$exists': True}}, 
{"_id": 0, "related_hashtags":1}) 
.hint([("epoch_creation_date", ASCENDING)]).explain() 
+0

Вам нужно будет сообщить нам, как эти индексы определены. – Philipp

+0

Привет, Филипп, ты имеешь в виду, как я создал индекс? Я использовал active_collection.create_index ([("epoch_creation_date", ASCENDING), ("related_hashtags", ASCENDING)]) например –

+0

Я имею в виду вызовы secureIndex, которые вы использовали для создания индексов. – Philipp

ответ

2

Вы создали (с именем epoch_creation_date_1_related_hashtags_1), но вы не используете его в этих подсказках.Вместо этого вы используете два однопоточных индекса, которые вы также создали (related_hashtags_1 и epoch_creation_date_1) в другом порядке.

Из этих двух индексов действует только epoch_creation_date_1, потому что вы не запрашиваете оба поля. Вы запрашиваете только один, и это 'epoch_creation_date': {'$exists': True}. Полевая фильтрация, которую вы выполняете с {"_id": 0, "related_hashtags":1}, выполняется на документах, которые были найдены этим запросом. В этот момент индексы больше не нужны. Это означает, что любой индекс на related_hashtags не сможет повысить производительность по этому запросу. Компонентный индекс (когда вы на самом деле его используете) может быть лучше, чем никакого индекса, но не так хорош, как индекс только для epoch_creation_date.

+0

Это имеет смысл, но продолжайте путать. Чтение Mongo docs по адресу: http://docs.mongodb.org/manual/tutorial/create-indexes-to-support-queries/ Говорят, что 'codedb.users.ensureIndex ({status: 1, user: 1})' был бы хорошим индексом для 'db.users.find ({status:" A "}, {user: 1, _id: 0})' –

+0

@OscarMoya Но похоже, что это было не то, что вы сделали. Вот почему я попросил вас предоставить команды sureIndex, которые вы использовали для создания индексов. – Philipp

+0

Я выполнил инструкции по http://api.mongodb.org/python/current/tutorial.html#indexing, чтобы создать индексы. Я начинаю думать, что PyMongo не может поддерживать создание таких составных индексов для многоядерных полей (какой звук в любом случае мне вряд ли подходит). Документы PyMongo не очень ясны по этому поводу. –

0

Хорошо, прочитав вопрос, я больше понимаю. Мультикидный индекс будет записывать индексную запись PER многозначную. Это означает, что если у вас есть 3 значения за related_hashtags за документ, ваш индекс фактически равен 3 раза и имеет 3 раза количество сканируемых значений (если моя математика там добавляется ...).

nscanned является счетчиком времени, в течение которого документ должен был быть просмотрен (счетчик нот, а не определенное количество уникальных документов), это означает, что из-за мультикидного индекса вам пришлось сканировать примерно 3 раза количество (тех же) документов, которые вы обычно использовали для первого запроса.

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

Я считаю, причина, по которой третий запрос настолько медленный, потому что индексы multikey не могут поддерживать indexOnly курсоры, поэтому MongoDB не мог использовать закрытые запросы там.

+0

Вы правы. Другие читатели могут видеть это по адресу: http://docs.mongodb.org/manual/tutorial/create-indexes-to-support-queries/ В документах говорится: «Индекс не может охватывать запрос, если: любое проиндексированное поле в любом из документов в коллекции содержится массив.Если индексированное поле является массивом, индекс становится индексом индекса с несколькими ключами и не может поддерживать закрытый запрос " –

Смежные вопросы