2016-05-04 2 views
1

ВведениеMongoDB очень медленно при использовании счета() на массиве

Моя коллекция насчитывает более 1 миллиона документов. Структура каждого документа одинакова и выглядит следующим образом:

{_id: "LiTC4psuoLWokMPmY", number: "12345", letter: "A", extra: [{eid:"jAHBSzCeK4SS9bShT", value: "Some text"}]} 

Итак, как вы можете видеть, мой extra поле представляет собой массив, который содержит небольшие объекты. Я пытаюсь вставить эти объекты как можно больше (пока я не приблизился к 16 МБ ограничения документа). И эти объекты обычно присутствуют в массиве extra большинства документов в коллекциях. Поэтому у меня обычно есть сотни тысяч одинаковых объектов.

У меня есть индекс на eid ключ в массиве extra. Я создал этот индекс с помощью этого:

db.collectionName.createIndex({"extra.eid":1}) 

Проблема

Я хочу, чтобы подсчитать, сколько extra поле объекта присутствует в коллекции. Я делаю это, используя это:

db.collectionName.find({extra: {eid: "jAHBSzCeK4SS9bShT"}}).count() 

В начале запрос выше очень быстрый. Но всякий раз, когда массив extra получает немного больше (более 20 объектов), он становится очень медленным.

С 3-4 объектами требуется менее 100 миллисекунд, но когда он становится больше, требуется гораздо больше времени. С 50 объектами он занимает 6238 миллисекунд.

Вопросы

  1. Почему это происходит?
  2. Как ускорить этот процесс?
  3. Есть ли другой способ, который выполняет этот процесс, но быстрее?
+0

Рассмотрите возможность создания индекса для «дополнительных». –

+0

@FelipeSulser К сожалению, это невозможно, потому что индексный ключ слишком велик. – stackyname

+0

Использует ли агрегацию работу быстрее, так как я не думаю, что использование find и count - правильный путь. Например db.collectionName.aggregate ({$ group: {_id: "$ extra.eid", count: {$ sum: 1}}}); –

ответ

3

Я столкнулся с similar problem. Уверен, что ваш запрос не попадает в ваш индекс.

Вы можете объяснить (запустите db.collectionName.find({extra: {eid: "jAHBSzCeK4SS9bShT"}}).explain() в оболочке Mongo), чтобы знать наверняка.

Причина в том, что в Mongo db.collectionName.find({extra: {eid: "jAHBSzCeK4SS9bShT"}}) это не то же самое, что и db.collectionName.find({"extra.eid": "jAHBSzCeK4SS9bShT"}). Первая форма не будет использовать ваш индекс, в то время как вторая форма будет (в качестве примера, хотя это не будет работать в вашем случае, потому что ваш поддокумент на самом деле является массивом). Не знаю, почему, но это, похоже, является причудой строителя запросов Mongo.

Я не нашел решения, кроме индексации всего поддокумента.

+0

Вау я этого не знал. Большое спасибо! Второй запрос в два раза быстрее.И вы были правы, первый не использует индекс. Вы сказали, что второй запрос не будет работать для меня; но он работает. Я что-то упускаю? – stackyname

+0

Это здорово, если он работает! Я просто не был уверен, потому что я использовал этот синтаксис только для поддокументов, которые не были массивами. Чтобы быть уверенным, вы можете запустить 'explain()' на нем и убедиться, что он использует индекс. Рад, что он работает быстрее :-) FWIW, я все еще не уверен, что это поведение предназначено или ошибка ... – Hashcut

+0

Это работает очень хорошо! Да, я использовал 'explain()' для проверки использования индекса, и только второй показал, что он используется. Я переработал поле 'extra', теперь он содержит более сложные объекты. Я вставил 70 объектов для каждого документа и с первым запросом (не используя индекс), count занял 7357 миллисекунд, где со вторым запросом (с использованием индекса) счетчик занял всего 104 миллисекунды. Надеюсь, это не ошибка :) Еще раз спасибо! – stackyname

Смежные вопросы