В моей базе данных есть уникальная коллекция твиттер-слов. Документ внутри него имеет следующую форму:
{
_id: <some-object-id>,
initial: "t",
word: "the",
count: 986,
tweets: <position information for the given word>
}
Я пробовал следующие коды для создания индексов:
db.tweet_words.create_index([("word", pymongo.ASCENDING), ("initial", pymongo.ASCENDING)], background=True)
и
db.tweet_words.create_index("word", background=True)
и
db.tweet_words.create_index([("word", pymongo.HASHED)], background=True)
Хотя использование этих индексов помогло ускорить выполнение команды обновления, она по-прежнему выполняется относительно медленно. Я думаю, что должен быть способ получше.
Вот мои команды обновления:
from pymongo import UpdateOne
# connect to db stuff
# create indexing using one of the approaches above
commands = []
for word in words: # this is actually not the real loop I've used but it fits for this example
# assume tweet_id's and position is calculated here
initial = word[0]
ret = {"tweet_id": tweet_id, "pos": (beg, end)} # additional information about word
command = UpdateOne({"word": word, "initial": initial}, # use query {"word": word} only if one of bottom two indexing strategy is chosen
{
"$setOnInsert": {"initial": initial},
"$inc": {"count": 1},
"$push": {"tweets": ret},
},
commands.append(command)
if len(commands) % 1000 == 0:
db.tweet_words.bulk_write(commands, ordered=False)
commands = []
Вы можете найти настоящий код здесь.
Вот результат работы pprint(db.tweet_words.find({"word": word}).explain()) (не удалось придумать, как использовать метод объяснения на UpdateOne или bulk_write), когда в коллекции присутствует ~ 130 тыс. Документов:
{'executionStats': {'allPlansExecution': [],
'executionStages': {'advanced': 1,
'alreadyHasObj': 0,
'docsExamined': 1,
'executionTimeMillisEstimate': 0,
'inputStage': {'advanced': 1,
'direction': 'forward',
'dupsDropped': 0,
'dupsTested': 0,
'executionTimeMillisEstimate': 0,
'indexBounds': {'initial': ['[MinKey, '
'MaxKey]'],
'word': ['["seval", '
'"seval"]']},
'indexName': 'word_1_initial_1',
'indexVersion': 2,
'invalidates': 0,
'isEOF': 1,
'isMultiKey': False,
'isPartial': False,
'isSparse': False,
'isUnique': False,
'keyPattern': {'initial': 1,
'word': 1},
'keysExamined': 1,
'multiKeyPaths': {'initial': [],
'word': []},
'nReturned': 1,
'needTime': 0,
'needYield': 0,
'restoreState': 0,
'saveState': 0,
'seeks': 1,
'seenInvalidated': 0,
'stage': 'IXSCAN',
'works': 2},
'invalidates': 0,
'isEOF': 1,
'nReturned': 1,
'needTime': 0,
'needYield': 0,
'restoreState': 0,
'saveState': 0,
'stage': 'FETCH',
'works': 2},
'executionSuccess': True,
'executionTimeMillis': 0,
'nReturned': 1,
'totalDocsExamined': 1,
'totalKeysExamined': 1},
'ok': 1.0,
'queryPlanner': {'indexFilterSet': False,
'namespace': 'twitter.tweet_words',
'parsedQuery': {'word': {'$eq': 'seval'}},
'plannerVersion': 1,
'rejectedPlans': [],
'winningPlan': {'inputStage': {'direction': 'forward',
'indexBounds': {'initial': ['[MinKey, '
'MaxKey]'],
'word': ['["seval", '
'"seval"]']},
'indexName': 'word_1_initial_1',
'indexVersion': 2,
'isMultiKey': False,
'isPartial': False,
'isSparse': False,
'isUnique': False,
'keyPattern': {'initial': 1,
'word': 1},
'multiKeyPaths': {'initial': [],
'word': []},
'stage': 'IXSCAN'},
'stage': 'FETCH'}},
'serverInfo': {'gitVersion': 'f288a3bdf201007f3693c58e140056adf8b04839',
'host': 'MostWanted',
'port': 27017,
'version': '4.0.4'}}
Есть ли в моем коде разрешимое узкое место? Или это так хорошо, как получается?
Обновил код. Это не настоящий код, который я использовал в своем проекте. Вот почему я по ошибке его пропускаю.
Да ... Я не вижу ничего очевидного, поэтому немного обеспокоен тем, что это не настоящий код, вы могли его упростить - особенно если вы только что пропустили нужную строку :)
В любом случае - заставьте его объяснить выполняемый запрос и убедитесь, что он решает использовать индексы ... нажатие на список, хотя, когда он становится большим, может включать переписывание страниц, хотя ... так что может быть это - трудно сказать. Я предлагаю начать с объяснения плана запроса и посмотреть, указывает ли это на что-нибудь очевидное.
Не знаю, как использовать метод explain для работы с bulk_write. Вместо этого я запросил слово и получил объяснение. Вы можете проверить результат выше.
Спасибо ... Я давно не использовал монго - так что не эксперт - просто советовал эту информацию. должен быть в самом Q, потому что он, надеюсь, поможет кому-то указать на что-то, если возможно ... удачи, тем не менее, с решением.
Текущий вывод объяснения запроса, который вы включили, указывает 'executionTimeMillis': 0` только с одним поиском по индексу и документу. Любые возможности для улучшения заключаются в сокращении ненужных накладных расходов (например, удалении неиспользуемых индексов) или поиске узких мест в коде или развертывании. Не могли бы вы предоставить более подробную информацию о том, что вы считаете медленным - пора ли выполнять операцию массовой записи? Если да: сколько документов вы вставляете / обновляете, какие ресурсы сервера у вас есть (в частности, RAM и диск) и каков общий dataSize для вашего развертывания?
Я пытаюсь найти уникальные слова примерно в 13 млн твитов. Если предположить, что в среднем твит содержит 10 слов, это означает, что будет выполнено около 130 миллионов команд вставки / обновления. В моей последней попытке я запускал скрипт почти 16 часов подряд, затем мне нужно его убить. Потому что он обработал около 1 миллиона твитов. У моего компьютера 28 ГБ оперативной памяти, а на жестком диске - Hitachi HDS721010CLA332. dataSize всей базы данных twitter - это {dataSize : 202887823327}, и вы можете найти настоящий код, который я запускал в этом посте.






Где вы сначала назначаете
commandsчему-то в своем коде?