Arhn - архитектура программирования

почему скорость сортировки mongodb по полю вложенного документа такая низкая?

в моей тестовой коллекции есть эти поля

{
    "block_number": 123123,
    "value": 555.55555
    "transfers": [
        {
            "from": "foo1", 
            "to": "bar1", 
            "amount": 111.111
        },
        {
            "from": "foo2", 
            "to": "bar2", 
            "amount": 222.222
        },
        ...
        {
            "from": "foo3", 
            "to": "bar3", 
            "amount": 100.100
        },
    ]
},
...
{
    ...
}

и я сделал такие индексы (в коде Python)

tx_collection.create_index("block_number")
tx_collection.create_index("transfers.amount")
tx_collection.create_index("value")

Почему два одинаковых запроса показывают разную скорость?

два запроса

  1. tx_collection.find({'block_number': {'$gte': 3243145}}, {'_id': 0}).sort('transfers.amount', -1).limit(100)
  2. tx_collection.find({'block_number': {'$gte': 3243145}}, {'_id': 0}).sort('value', -1).limit(100)

И код Python для проверки времени выполнения выглядит так

    start = time.time()

    txs = tx_collection.find({'block_number': {'$gte': 3243145}}, {'_id': 0}).sort('transfers.amount', -1).limit(100)
    # txs = tx_collection.find({'block_number': {'$gte': 3243145}}, {'_id': 0}).sort('value', -1).limit(100)

    for tx in txs:
        print(tx)

    done = time.time()
    print(done - start)

время исполнения

  • 1-й запрос: около 0,1 сек.
  • 2-й запрос: около 10 секунд

Почему они слишком разные?

JFYI. у mongdb есть 5 сегментов, и я запускаю этот запрос на mongos, используя код python.


Дополнительный тест.

Когда я тестирую запрос ниже на клиенте mongodb,

db.getCollection('transaction').find({}).sort({"transfers.amount":1})

он выдает сообщение об ошибке, например

"Executor error during find command: OperationFailed: Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit.",

Похоже, индекс на transfers.amount не работает

Когда я проверил с помощью db.getCollection('transaction').getIndexes(), я подтвердил, что индекс на самом transfers.amount был установлен правильно, например

    {
        "v" : 2,
        "key" : {
            "transfers.amount" : 1.0
        },
        "name" : "transfers.amount_1",
        "ns" : "crossangle.transaction"
    }

  • Не могли бы вы добавить вывод вашего запроса с помощью explain? Чтобы можно было отслеживать выигрышный план в вашем запросе. 08.10.2019
  • Помогает ли этот ответ? stackoverflow.com/questions/36142299/ 08.10.2019
  • @VijayRajpurohit Спасибо за ваш комментарий. Но похоже, что моя точка зрения связана с transfers.amount. 08.10.2019
  • @kevinadi Спасибо за ваш комментарий. полностью прочитал. Но мой случай в том, что индекс на transfers.amount не работает. 08.10.2019
  • @ dingyo777 это потому что у тебя sort. MongoDB предпочтет индекс, который может помочь с сортировкой, и проигнорирует все остальные индексы, поскольку обычно для каждого запроса используется только один индекс. Существует ограничение в 32 МБ на использование памяти sort. Чтобы обслуживать как find, так и sort, вам нужен составной индекс, как подробно описано в ответе stackoverflow.com/questions/36142299/. Почему один запрос занял больше времени, чем другой, требуется дополнительная информация, например explain() вывод запроса. 09.10.2019
  • @ dingyo777 ответ в stackoverflow.com/questions/36142299/ на самом деле затрагивает эту оптимизацию и причины, но я понимаю, почему это не сразу очевидно. То, что вы видите, — это состояние ошибки при неиспользовании составного индекса. 09.10.2019
  • @kevinadi Спасибо за ваш ответ. Собственно, я уже прочитал ссылку, которой вы поделились. Но мой случай, в котором используется индекс с несколькими ключами, не очень хорошо объясняется по ссылке. Когда я тестировал с db.getCollection('transaction').find({}).sort({"transfers.amount":1}), он достиг максимального предела памяти. Это означает, что сортировка по подполям не использует многоключевой индекс. 09.10.2019
  • @ dingyo777 да, transfers и transfers.amount - это два очень разных индекса, многоключевые или нет. transfers индексирует вложенные документы в целом, а transfers.amount индексирует только номер. 09.10.2019
  • @kevinadi Спасибо за ваш ответ. Итак, в mongodb кажется, что невозможно отсортировать документ по индексу подполя вложенного документа. 10.10.2019
  • @ dingyo777 возможно, но чтобы сортировка не ограничивалась 32 МБ, вам понадобится индекс. Уместный вопрос: учитывая документ, содержащий массив значений, каким, по вашему мнению, должен быть результат сортировки? Но это вообще уход в другую тему, где новый вопрос будет лучше. С исходным вопросом о скорости запроса вам нужно опубликовать explain() вывод обоих запросов. 10.10.2019
  • @kevinadi Спасибо за ваш ответ. Хм, уже есть индекс для поля вложенного документа, такого как transfers.amount. И я полностью согласен с вами, что я создам новый вопрос. 10.10.2019
  • @kevinadi Я создал здесь новый вопрос: stackoverflow.com/questions/58314180/ 10.10.2019

Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..