Почему полнотекстовый поиск осколков MongoDB происходит намного быстрее, чем через экземпляр диспетчера кластера (mongos)?

Я был очень недоволен результатами полнотекстового поиска в MongoDB, поэтому я искал внешние решения. С относительно небольшой коллекцией из 25 миллионов документов, помещенных на 8 мясистых машинах (4 осколка с избыточностью), я вижу, что некоторые запросы занимают 10 секунд. Это ужасно. На жаворонке я попробовал 10-секундный запрос к осколкам напрямую, и кажется, что монгосы посылают запросы на черепах поочередно, а не параллельно. Через 4 осколка я видел время поиска 2,5 секунды на одном осколке, а остальные 3 осколки менее 2 секунд каждый. Это всего менее 8,5 секунд, но потребовалось 10 до монго. Facepalm.

Могут ли кто-то подтвердить эти запросы на чередование, выполняются серийно? Или предложите другое объяснение?

Каковы подводные камни для непосредственного запроса осколков?

Мы находимся на 4.0, и запрос выглядит так:

db.items.aggregate(
[
   { "$match" : {
    "$text" : { "$search" : "search terms"}
      }
   }, 
   { "$project": { "type_id" : 1, "source_id": 1 } },
   { "$facet" : { "types" : [ { "$unwind" : "$type_id"} , { "$sortByCount" : "$type_id"}] , "sources" : [ { "$unwind" : "$source_id"} , { "$sortByCount" : "$source_id"}]}}
]
);

Я допустил ошибку раньше, это запрос, который имеет проблему. И я поговорил с экспертом MongoDB и был увлечен большой частью того, что происходит (я думаю), но рад видеть, что другие должны сказать, чтобы я мог заплатить щедрость и сделать ее официальной.

Ответ 1

Может ли кто-нибудь подтвердить, что эти запросы к шардам выполняются последовательно? Или предложить какое-то другое объяснение?

Без ключа шарда в запросе запрос отправляется всем шардам и обрабатывается параллельно. Однако результаты всех осколков будут объединены в первичном осколке, и, таким образом, он будет ожидать возвращения самого медленного осколка.

Каковы подводные камни для непосредственного обращения к осколкам?

Вы можете включить осиротевшие документы. Запрос через mongos также проверяет потерянные документы для обеспечения согласованности данных. Следовательно, запросы через mongos имеют больше накладных расходов, чем запросы непосредственно из каждого шарда.

Измерено с использованием времени запроса Robo 3T

Использование Robo 3T неправильно измеряет время запроса. По умолчанию Robo 3T возвращает первые 50 документов. В реализациях драйверов, если количество возвращаемых документов превышает размер пакета по умолчанию, для извлечения всех документов будут выполняться запросы getmore к базе данных. Robo 3T дает вам только первый пакет, то есть набор результатов.

Чтобы оценить ваш запрос, добавьте explain('executionStats') к вашему запросу. Падение производительности - это, вероятно, передача данных между осколками. Поскольку в запросе отсутствует ключ сегмента, результаты всех сегментов должны быть отправлены в сегмент до объединения. Общее время - это не только время запроса (нахождения документов) из механизма Монго, но и время поиска документов.

Выполните команду ниже, и вы увидите входные данные от каждого шарда, чтобы лучше оценить ваш запрос.

db.items.explain('executionStats').aggregate(
[
   { "$match" : {
    "$text" : { "$search" : "search terms"}
      }
   }, 
   { "$project": { "type_id" : 1, "source_id": 1 } },
   { "$facet" : { "types" : [ { "$unwind" : "$type_id"} , { "$sortByCount" : "$type_id"}] , "sources" : [ { "$unwind" : "$source_id"} , { "$sortByCount" : "$source_id"}]}}
]
);