Сортировка в MongoDB при текстовом поиске занимает кучу времени.

12
Станислав
На сайте с 27.12.2009
Offline
251
276

Монга сыпет кучу информации о медленных запросах, я уже и не знаю куда копать, понятно только то что все это из за сортировки в базе данных.

Вот пример быстрого запроса без сортировки

const result = await CollectionModel.aggregate([
        {
            $match: {
                "$text": { $search: "ищу какие то красные кеды"}
            }
        },  {
            $limit: 10
        }
    ]).explain(true)
{
  explainVersion: '1',
  queryPlanner: {
    namespace: 'database.tables',
    parsedQuery: { '$text': [Object] },
    indexFilterSet: false,
    queryHash: 'CF6F4CEE',
    planCacheShapeHash: 'CF6F4CEE',
    planCacheKey: '08852285',
    optimizationTimeMillis: 0,
    optimizedPipeline: true,
    maxIndexedOrSolutionsReached: false,
    maxIndexedAndSolutionsReached: false,
    maxScansToExplodeReached: false,
    prunedSimilarIndexes: false,
    winningPlan: {
      isCached: false,
      stage: 'LIMIT',
      limitAmount: 10,
      inputStage: [Object]
    },
    rejectedPlans: []
  },
  executionStats: {
    executionSuccess: true,
    nReturned: 10,
    executionTimeMillis: 0,
    totalKeysExamined: 10,
    totalDocsExamined: 10,
    executionStages: {
      isCached: false,
      stage: 'LIMIT',
      nReturned: 10,
      executionTimeMillisEstimate: 0,
      works: 11,
      advanced: 10,
      needTime: 0,
      needYield: 0,
      saveState: 0,
      restoreState: 0,
      isEOF: 1,
      limitAmount: 10,
      inputStage: [Object]
    },
    allPlansExecution: []
  },
  queryShapeHash: 'F84DD279882C2CD1580879CB35C9D2FAffffffF5FFA176BA8790E6B7871E6C527AF54',
  command: {
    aggregate: 'tables',
    pipeline: [ [Object], [Object] ],
    cursor: {},
    '$db': 'database'
  },
  serverInfo: {
    host: 'cvggggg.novalocal',
    port: 27017,
    version: '8.0.8',
    gitVersion: '7f52660c14217ed2c8d3240fdh63a2291a4fe6abd'
  },
  serverParameters: {
    internalQueryFacetBufferSizeBytes: 104857600,
    internalQueryFacetMaxOutputDocSizeBytes: 104857600,
    internalLookupStageIntermediateDocumentMaxSizeBytes: 104857600,
    internalDocumentSourceGroupMaxMemoryBytes: 104857600,
    internalQueryMaxBlockingSortMemoryUsageBytes: 104857600,
    internalQueryProhibitBlockingMergeOnMongoS: 0,
    internalQueryMaxAddToSetBytes: 104857600,
    internalDocumentSourceSetWindowFieldsMaxMemoryBytes: 104857600,
    internalQueryFrameworkControl: 'trySbeRestricted',
    internalQueryPlannerIgnoreIndexWithCollationForRegex: 1
  },
  ok: 1
}

Время выполнения 0ms

А теперь тот же запрос с сортировкой

const result = await CollectionModel.aggregate([
        {
            $match: {
                "$text": { $search: "ищу какие то красные кеды"}
            }
        }, {
            $sort: { score: { $meta: "textScore" } }
        }, {
            $limit: 10
        }
    ]).explain(true)
{
  explainVersion: '1',
  queryPlanner: {
    namespace: 'database.tables',
    parsedQuery: { '$text': [Object] },
    indexFilterSet: false,
    queryHash: 'A6423DDB',
    planCacheShapeHash: 'A6423DDB',
    planCacheKey: '82516035',
    optimizationTimeMillis: 0,
    optimizedPipeline: true,
    maxIndexedOrSolutionsReached: false,
    maxIndexedAndSolutionsReached: false,
    maxScansToExplodeReached: false,
    prunedSimilarIndexes: false,
    winningPlan: {
      isCached: false,
      stage: 'SORT',
      sortPattern: [Object],
      memLimit: 104857600,
      limitAmount: 10,
      type: 'default',
      inputStage: [Object]
    },
    rejectedPlans: []
  },
  executionStats: {
    executionSuccess: true,
    nReturned: 10,
    executionTimeMillis: 980,
    totalKeysExamined: 214028,
    totalDocsExamined: 195116,
    executionStages: {
      isCached: false,
      stage: 'SORT',
      nReturned: 10,
      executionTimeMillisEstimate: 967,
      works: 409161,
      advanced: 10,
      needTime: 409150,
      needYield: 0,
      saveState: 51,
      restoreState: 51,
      isEOF: 1,
      sortPattern: [Object],
      memLimit: 104857600,
      limitAmount: 10,
      type: 'default',
      totalDataSizeSorted: 55577,
      usedDisk: false,
      spills: 0,
      spilledDataStorageSize: 0,
      inputStage: [Object]
    },
    allPlansExecution: []
  },
  queryShapeHash: '3F5BE8C71C85D64E7F8EC4182830F8F77345ty7yh982F7A97726C6407A102DC1BA0',
  command: {
    aggregate: 'tables',
    pipeline: [ [Object], [Object], [Object] ],
    cursor: {},
    '$db': 'database'
  },
  serverInfo: {
    host: 'fghh.novalocal',
    port: 27017,
    version: '8.0.8',
    gitVersion: '7f52660c14217ed2c8ymndd0f823a2291a4fe6abd'
  },
  serverParameters: {
    internalQueryFacetBufferSizeBytes: 104857600,
    internalQueryFacetMaxOutputDocSizeBytes: 104857600,
    internalLookupStageIntermediateDocumentMaxSizeBytes: 104857600,
    internalDocumentSourceGroupMaxMemoryBytes: 104857600,
    internalQueryMaxBlockingSortMemoryUsageBytes: 104857600,
    internalQueryProhibitBlockingMergeOnMongoS: 0,
    internalQueryMaxAddToSetBytes: 104857600,
    internalDocumentSourceSetWindowFieldsMaxMemoryBytes: 104857600,
    internalQueryFrameworkControl: 'trySbeRestricted',
    internalQueryPlannerIgnoreIndexWithCollationForRegex: 1
  },
  ok: 1
}

Время выполнения executionTimeMillisEstimate: 967

И это еще относительно быстро, есть запросы которые выполняются и более 10 секунд

Вопрос в том что можно придумать, возможно использовать какую то связку mongodb + что то там, или как то по другому выборку производить. Любая информация будет полезна для меня.

Мы там, где рады нас видеть.
L
На сайте с 10.02.2015
Offline
245
#1

1. Вы умеете читать explain mongo?
2. Сколько строк найдено по индексу в обоих случаях?
3. Может делать запрос не через агрегацию, если там ее нет? Хотя вряд в этом дело.

temniy
На сайте с 15.03.2008
Offline
254
#2
Не используйте Монго, очень тормозная и тем более, чем больше данных. 
⭐ Лучший хостинг от 4 евро, VPS от 6 евро, VPN недорого - разные локации - любые карты - скидки до 20% - https://fornex.com/c/ffi2e3/ru/services/
SA
На сайте с 12.04.2024
Offline
32
#3
А почему так много данных в ответе? Какой результат должен быть по запросу Красные кроссовки? Явно не порт сервера.
lutskboy
На сайте с 22.11.2013
Offline
184
#4
может сфинс взять или мантикору?
Станислав
На сайте с 27.12.2009
Offline
251
#5
livetv #:

1. Вы умеете читать explain mongo?
2. Сколько строк найдено по индексу в обоих случаях?
3. Может делать запрос не через агрегацию, если там ее нет? Хотя вряд в этом дело.

1. Не особо

2. Explain лжет, это один и тот же запрос и в обоих запросах под 200к документов, то что он выводит при первом запросе информацию о всего 10 документах, это не правда. Если вы конечно об этом.

3. Даже если через find, разницы тут не будет к сожалению.

Станислав
На сайте с 27.12.2009
Offline
251
#6
temniy #:
Не используйте Монго, очень тормозная и тем более, чем больше данных. 

Ну а что использовать вместо нее? С таким же удобным хранением  данных.


lutskboy #:
может сфинс взять или мантикору?

Использовать из в связке с mongodb?

damn-doubleclick
На сайте с 10.09.2021
Offline
54
#7
Станислав #:

Ну а что использовать вместо нее? С таким же удобным хранением  данных.

Mongo путь в никуда, лучше MariaDB, либо Postgre 

Лучший хостер с адекватными сис. админами: https://clck.ru/35zGfN
S3
На сайте с 29.03.2012
Online
340
#8
damn-doubleclick #:
Mongo путь в никуда

Не выдумывай того, что не знаешь. Монга - отличная вещь, если уметь работать с такими базами. У нас миллионы ответов хранятся в Динаме и норм. Предлагать реляционки вместо noSQL - не понимать задачи. 

damn-doubleclick #:
либо Postgre 

не существует такого

L
На сайте с 10.02.2015
Offline
245
#9
Станислав #:

1. Не особо

2. Explain лжет, это один и тот же запрос и в обоих запросах под 200к документов, то что он выводит при первом запросе информацию о всего 10 документах, это не правда. Если вы конечно об этом.

3. Даже если через find, разницы тут не будет к сожалению.

1. +1. Можно использовать gui-шный от MongoDB Compass.
2. В первом случае ему достаточно 10 документов. Он индекс просматривает на 10 документов. А 200к может быть и сложно сортировать. Возможно какие-то слова слишком частые в базе. Какой размер базы в штуках и метрах?

Станислав
На сайте с 27.12.2009
Offline
251
#10
damn-doubleclick #:

Mongo путь в никуда, лучше MariaDB, либо Postgre 

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

В MongoDB все устраивает и только вот этот косяк с сортировкой при поиске документов через $text очень сильно огорчает, это единственно от чего меня воротит, но уверен в том что либо я делаю что то не так, либо можно делать как то по другому, к примеру использовать в связке монго с чем то еще только в подобных запросах.

Может я индекс как то не так создаю, сейчас для такого поля создан индекс вот так

Collection.index({ subscribe: 'text', "title.ru": 'text', "title.en": "text" }, { default_language: "russian" })

А вот для сортировки создать индекс не могу 

{ score: { $meta: "textScore" } }

Ведь score в документе нет и он генерируется самой mongo, возможно как то не правильно я все это добро делаю.

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

С сортировкой по полям в документе всё работает быстро, для них индексы созданы правильные.

12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий