Функции AVG и SUM в MongoDB, какие-нибудь советы? - PullRequest
7 голосов
/ 06 сентября 2011

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

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

Документы в запрашиваемой коллекции напоминают эту структуру (с множеством других полей):

{
    "_id": ObjectId('4e650107580fd649e5000005'),
    "date_added": ISODate("2011-09-05T00:00:00Z"),
    "value": 1500
}

В моем приложении не всегда возможен предварительный расчет таких сумм, как суммы, потому что выбор суммируемых значений может изменяться (в зависимости от диапазонов дат - например, между начальной датой и конечной датой, каково среднее значение). Это аналогичная проблема с предварительным вычислением средних значений.

Из того, что я прочитал, MapReduce определенно не идеален для поиска в реальном времени (то есть по запросу), так что об этом тоже не может быть и речи.

В данный момент я запрашиваю коллекцию следующим образом: (примечание: это использует pymongo)

response = request.db['somecollection'].find(
    {
        'date_added': {
            '$gte': date_start,
            '$lte': date_end
        }
    },
    {
        'value':1
    }
).limit(500)

Затем выполняем вычисления в Python, используя цикл for над ответом. Предел в 500 результатов является произвольным, чтобы он не стал слишком медленным. Я только получаю значение, и ни одно из других полей.

Это самый эффективный метод выполнения этой калькуляции, или есть другие методы для достижения того, что мне нужно?

Предостережения:

  • Я не могу использовать функцию group, потому что, вероятно, буду использовать шардинг в будущем
  • Я не могу использовать MapReduce, потому что эта функция будет использоваться пользователями на лету
  • Я не могу предварительно рассчитать многие из моих сумм / средних, потому что выбор значений для суммирования / среднего почти всегда отличается
  • Я просмотрел stackoverflow и Интернет, чтобы попытаться найти рекомендацию о том, как это делать, и он довольно открытый

EDIT:

Я должен отметить, что количество документов, возвращаемых по запросу, который я разместил выше, может быть любым от 1 до сотен, но, вероятно, максимальное количество возвращаемых документов будет около 150 (в среднем около 60 или 70)

Ответы [ 4 ]

4 голосов
/ 06 сентября 2011

Дайте карту - уменьшите попытку, вероятно, она не такая медленная, как вы думаете. Я использовал его для агрегации в реальном времени по некоторым большим наборам данных, и, хотя иногда это происходит не слишком быстро, чаще это нормально. Лучше всего, если вы сможете отфильтровать размер исходных данных, которые вы агрегируете, например ::10000

db.collection.mapReduce(m, r, { query : { year: 2011 } });

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

3 голосов
/ 06 сентября 2011

Примечания MongoDB

ОК, поэтому в настоящее время существуют серьезные проблемы с Map / Reduce и агрегированием.

Большое предупреждение: Экземпляр MongoDB может иметь только одинэкземпляр "движка JavaScript" .Это означает, что вы не можете запустить два одновременных Map / Reduces на сервере.И вы получаете только одно ядро ​​для запуска карты-редукции.

В случае того, что вы делаете, вы, в основном, «катаете свое» M / R.Недостатком является дополнительный сетевой трафик.Плюс в том, что теперь вы можете добавить больше ядер для этой проблемы (с веб-серверов).

Ваш ключевой вопрос

Я не могу пересчитатьмного моих сумм / средних, потому что выбор значений для суммирования / усреднения почти всегда отличается

Не существует общего метода для оптимизации «всех возможных» запросов.Если вы хотите, чтобы система могла суммировать и агрегировать по каждому полю для каждого диапазона, то вы в конечном итоге найдете набор полей / диапазонов, которые слишком велики.

Способ «решить» этоуменьшите набор полей и диапазонов.

Поэтому сохраняйте ежедневные / почасовые счетчики и суммируйте их.По крайней мере, вы уменьшаете количество документов, которые необходимо отсканировать, чтобы ответить на ваш запрос.

2 голосов
/ 06 сентября 2011

Простой ответ:

  1. Если это возможно, пересчитать все, что вы можете рассчитать.
  2. Если вам нужны агрегированные данные по диапазонам дат, и агрегация должна работать как можно быстрее, используйте карту/ Снижение + Sharding для распределения расчетов по нескольким машинам.

Но в то же время руководство mongodb говорит:

Цена использования MapReduce - скорость: группа не особенно быстра, но MapReduce медленнее и не должна бытьиспользуется в «реальном времени». Вы запускаете MapReduce в качестве фонового задания, оно создает коллекцию результатов, а затем вы можете запросить эту коллекцию в режиме реального времени.

Так что, похоже, mongodb не самый лучшийрешение для агрегации данных в реальном времени.

1 голос
/ 20 октября 2011

MongoDB планируется получить собственные функции агрегирования для таких вещей, как sum / avg / min / max в версии 2.1.1 (в настоящее время планируется на 1 ноября 2011 г.). Для получения более подробной информации и статуса см. Вопрос по адресу: https://jira.mongodb.org/browse/SERVER-447

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...