В приведенном ниже коде я запрашиваю дату и сортирую по имени (может показаться странным, что я не индексирую поле даты, но я делаю это, чтобы избежать сортировки в памяти, поэтому я индексирую по имени). Если я запускаю объяснение, я получаю следующее:
-> index on name
cursor: BtreeCursor name_1
scanAndOrder: False
nscanned: 1000
nscannedObjects: 1000
n:49
millis:1
Затем, если я создам составной индекс с именем и датой, я получу следующий результат:
-> index on name + date
cursor: BtreeCursor name_1_date_1
scanAndOrder: False
nscanned: 1000
nscannedObjects: 1000
n:49
millis:1
Даже если мой запрос не содержит индекса или его префиксов, на мой взгляд, во втором случае индекс должен иметь возможность напрямую читать поле даты из индекса, поэтому nscannedObject должен быть равен n = 49. Действительно, вся информация уже есть. в индексе и количество отсканированных документов должно быть равно количеству возвращенных результатов. Кажется, здесь не тот случай. Я ошибаюсь или делаю что-то не так?
import pymongo
from pymongo import MongoClient
import datetime
import random
def printCursorExplain(e):
print 'cursor: ' + e['cursor']
print 'scanAndOrder: ' + str(e['scanAndOrder'])
print 'nscanned: ' + str(e['nscanned'])
print 'nscannedObjects: ' + str(e['nscannedObjects'])
print 'n:' + str(e['n'])
print 'millis:' + str(e['millis'])
print '---------------------------------------------------------------------------------\n'
client = MongoClient()
db = client.DBQStackOverflow
name_list = ["Sylvain", "Tweety", "Toto", "Titi", "Sylvester"]
YEAR_LIST = [2014]
def generateRandomDate():
YYYY = YEAR_LIST[random.randint(0,len(YEAR_LIST)-1)]
MM = random.randint(1,12)
DD = random.randint(1,28)
date = datetime.datetime(YYYY, MM, DD)
return date
def insert():
for i in range(0, 1000):
start_date = generateRandomDate()
name = name_list[random.randint(0,len(name_list)-1)]
db.collection.insert( {"date": start_date, "name" :name})
insert()
YYYY = 2014
MM = 5
DD = 1
dateCIS = datetime.datetime(YYYY, MM, DD)
YYYY = 2014
MM = 5
DD = 12
dateCIE = datetime.datetime(YYYY, MM, DD)
queryDict = {"date" : {"$gte": dateCIS, "$lte": dateCIE}}
db.collection.create_index([("name", pymongo.ASCENDING)])
db.collection.create_index([("name", pymongo.ASCENDING),("date", pymongo.ASCENDING)], pymongo.ASCENDING)
print "-> index on name"
cursor1 = db.collection.find(queryDict).hint([("name", pymongo.ASCENDING)]).sort([("name", pymongo.ASCENDING)])#.limit(100)
e1 = cursor1.explain()
printCursorExplain(e1)
print "-> index on name + date"
cursor2 = db.collection.find(queryDict).hint([("name", pymongo.ASCENDING),("date", pymongo.ASCENDING)]).sort([("name", pymongo.ASCENDING)])#.limit(100)
e2 = cursor2.explain()
printCursorExplain(e2)