Почему PyMongo count_documents медленнее, чем count? - PullRequest
0 голосов
/ 08 сентября 2018

В db['TF'] У меня около 60 миллионов записей.

Мне нужно получить количество записей.

Если я запускаю db['TF'].count(), он сразу возвращается.

Если я запускаю db['TF'].count_documents({}), это так долго, прежде чем я получу результат.

Однако метод count устарел.

Итак, как быстро получить количество при использовании count_documents? Есть ли какие-то аргументы, которые я пропустил?

Я прочитал документ и код, но ничего не нашел.

Большое спасибо!

Ответы [ 2 ]

0 голосов
/ 29 декабря 2018

Как уже упоминалось здесь , поведение не является специфичным для PyMongo.

Причина в том, что метод count_documents в PyMongo выполняет запрос агрегации и не использует метаданные. см. collection.py # L1670-L1688

pipeline = [{'$match': filter}]
if 'skip' in kwargs:
    pipeline.append({'$skip': kwargs.pop('skip')})
if 'limit' in kwargs:
    pipeline.append({'$limit': kwargs.pop('limit')})
pipeline.append({'$group': {'_id': None, 'n': {'$sum': 1}}})
cmd = SON([('aggregate', self.__name),
           ('pipeline', pipeline),
           ('cursor', {})])
if "hint" in kwargs and not isinstance(kwargs["hint"], string_type):
    kwargs["hint"] = helpers._index_document(kwargs["hint"])
collation = validate_collation_or_none(kwargs.pop('collation', None))
cmd.update(kwargs)
with self._socket_for_reads(session) as (sock_info, slave_ok):
    result = self._aggregate_one_result(
        sock_info, slave_ok, cmd, collation, session)
if not result:
    return 0
return result['n']

Эта команда имеет то же поведение , что и метод collection.countDocuments.

При этом, если вы хотите обменять точность на производительность, вы можете использовать метод estimated_document_count, который, с другой стороны, отправляет команду count на база данных с тем же поведением , что и collection.estimatedDocumentCount См. collection.py # L1609-L1614

if 'session' in kwargs:
    raise ConfigurationError(
        'estimated_document_count does not support sessions')
    cmd = SON([('count', self.__name)])
    cmd.update(kwargs)
    return self._count(cmd)

Где self._count - помощник , отправляющий команду.

0 голосов
/ 08 сентября 2018

дело не в пимонго, а в монго.

count - встроенная функция монго. он не считает все документы.

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

count_documents получить объект запроса означает, что ему придется зацикливать бросать все перекодировки для подсчета. из-за того, что вы ничего не отправляете, ему придется пробежаться по всем 60-миллионным записям, и поэтому его медленная

на основе комментария @Stennie

Вы можете использоватьtimate_document_count () в PyMongo 3.7+, чтобы вернуть быстрый подсчет на основе метаданных коллекции. Исходное значение count () устарело, поскольку поведение различалось (по сравнению с фактическим количеством) в зависимости от того, были ли предоставлены критерии запроса. Более новый API драйвера более преднамерен в отношении результата

...