У меня было поведение в поведении с помощью отдельного запроса mongodb. В настоящее время я использую версию 2.6.10. Хорошо, давайте создадим простую коллекцию для теста с объяснениями.MongoDB не использует индексы для отдельных с простым запросом
from pymongo import MongoClient
import random
client = MongoClient('127.0.0.1', 27017)
client.DBTEST.random.remove({})
value = 0
BATCH_LEN = 16384
BATCH = []
for i in xrange(0, 500000):
BATCH.append({
"product": "value_uniq_1",
"number": value
})
if random.randint(0, 100) <= 1:
value = i
if len(BATCH) > BATCH_LEN:
client.DBTEST.random.insert(BATCH)
BATCH = []
client.DBTEST.random.insert(BATCH)
BATCH = []
Ok, это создаст коллекцию Чич содержит документы, как этот
╔══════════════╦════════╗
║ product ║ number ║
╠══════════════╬════════╣
║ value_uniq_1 ║ 1 ║
║ value_uniq_1 ║ 1 ║
║ value_uniq_1 ║ 1 ║
║ value_uniq_1 ║ 56 ║
║ value_uniq_1 ║ 56 ║
║ value_uniq_1 ║ 56 ║
║ ... ║ ... ║
║ value_uniq_1 ║ 150054 ║
║ value_uniq_1 ║ 150054 ║
║ value_uniq_1 ║ 150054 ║
╚══════════════╩════════╝
Теперь у меня есть только 1 уникальное значение для product
, но в ближайшем будущем (1 неделя) она увеличится до около 30 различных значений строк, как это:
╔══════════════╦════════╗
║ product ║ number ║
╠══════════════╬════════╣
║ value_uniq_1 ║ 1 ║
║ value_uniq_1 ║ 1 ║
║ value_uniq_1 ║ 1 ║
║ value_uniq_1 ║ 56 ║
║ value_uniq_1 ║ 56 ║
║ value_uniq_1 ║ 56 ║
║ ... ║ ... ║
║ value_uniq_1 ║ 150054 ║
║ value_uniq_1 ║ 150054 ║
║ value_uniq_1 ║ 150054 ║
║ value_uniq_2 ║ 987 ║
║ value_uniq_2 ║ 987 ║
║ value_uniq_2 ║ 987 ║
╚══════════════╩════════╝
Ok, я закончил с моей структуры данных, теперь давайте посмотрим немного MongoDB запросов.
Моя основная цель - получить все уникальные значения number
для определенного product
.
Я делаю это так:
db.random.distinct("number", {product: "value_uniq_1"})
Хорошо, это не совсем многословным для отладки, и я буду использовать db.runCommand
в следующих строках. Но, теперь, позволяет избежать использования запросов для отчетливого и внешнего вида stats
раздела:
db.runCommand({distinct: 'random', key:'number'})
"stats" : {
"n" : 500000,
"nscanned" : 500000,
"nscannedObjects" : 500000,
"timems" : 479,
"cursor" : "BasicCursor"
},
Это нормально, потому что мы не создавать индексы еще, позволяет добавлять к number
поля:
db.random.createIndex({number: 1})
ReRun предыдущего запрос:
db.runCommand({distinct: 'random', key:'number'})
"stats" : {
"n" : 10005,
"nscanned" : 10005,
"nscannedObjects" : 0,
"timems" : 83,
"cursor" : "DistinctCursor"
},
Отлично, он использует индексы, и все работает нормально! nscannedObjects !!!
Хорошо, давайте добавим запрос для отчетливый:
db.runCommand({distinct: 'random', key:'number', query: {product: "value_uniq_1"}})
"stats" : {
"n" : 500000,
"nscanned" : 500000,
"nscannedObjects" : 500000,
"timems" : 694,
"cursor" : "BasicCursor"
},
Это не то, что мы ожидали ("nscannedObjects": 500000), НО, нет индекса для продукта, позволяет создать некоторые один:
db.random.createIndex({product: 1, number: -1})
Нет никакой разницы в направлении, любая комбинация продукт: 1, номер -1 ИЛИ продукт -1, номер 1, ИЛИ продукт: 1, номер: 1 дает такое же поведение. Я проверил все комбинации.
db.runCommand({distinct: 'random', key:'number', query: {product: "value_uniq_1"}})
"stats" : {
"n" : 500000,
"nscanned" : 500000,
"nscannedObjects" : 500000,
"timems" : 968,
"cursor" : "BtreeCursor product_1_number_-1"
},
WTF Продолжается? Почему он сканирует всю коллекцию с индексом? В настоящее время вся коллекция содержит только одно значение продукта, и я не могу догадаться, что будет с разными продуктами. Почему это так медленно с обычным явным запросом? 1 сек слишком медленно ...
Я не хочу использовать отдельную коллекцию для каждого product
, она сумасшедшая и неэффективная, потому что мне нужны общие запросы между всеми продуктами. Моя реальная БД содержит более 5 миллионов номеров на один продукт, и для этого запроса требуется больше 3 секунд.
Возможный дубликат [MongoDB - отчетливый с запросом не использует индексы] (http://stackoverflow.com/questions/36006208/mongodb-distinct-with-query-doesnt-use -Indexes) – Robert