Подходы MongoDB для хранения больших объемов метрик / аналитических данных

#database-design #mongodb #statistics #analytics

#проектирование базы данных #mongodb #Статистика #аналитика

Вопрос:

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

Нам нужно записывать действия с указанием имени страницы, клиента и типа действия. В идеале нам нужна статистика, которая идет вниз по уровню год / месяц / день / час, нам не нужны просмотры в секунду или минуту, и мы не заботимся о них. Хотя эта структура документа выглядит нормально, я знаю, что 100 vistors сгенерируют 100 новых документов.

 { 
  "_id" : ObjectId( "4dabdef81a34961506040000" ),
  "pagename" : "Hello",
  "action" : "view",
  "client" : "client-name",
  "time" : Date( "Mon Apr 18 07:49:28 2011" )
}
  

Есть ли наилучший практический способ сделать это, используя $ inc или ограниченные коллекции?

Ответ №1:

Обновленный ответ

Взломанные совместно в оболочке mongo:

 use pagestats;

// a little helper function
var pagePerHour = function(pagename) {
    d = new Date();
    return {
        page : pagename,
        year: d.getUTCFullYear(),
        month: d.getUTCMonth(),
        day : d.getUTCDate(),
        hour: d.getUTCHours(),
    }
}

// a pageview happened
db.pagestats.update(
    pagePerHour('Hello'),
    { $inc : { views : 1 }},
    true ); //we want to upsert

// somebody tweeted our page twice!
db.pagestats.update(
    pagePerHour('Hello'),
    { $inc : { tweets : 2 }},
    true ); //we want to upsert

db.pagestats.find();
// { "_id" : ObjectId("4dafe88a02662f38b4a20193"),
//   "year" : 2011, "day" : 21, "hour" : 8, "month" : 3,
//   "page" : "Hello",
//   "tweets" : 2, "views" : 1 }

// 24 hour summary 'Hello' on 2011-4-21
for(i = 0; i < 24; i  ) {
    //careful: days (1-31), month (0-11) and hours (0-23)
    stats = db.pagestats.findOne({ page: 'Hello', year: 2011, month: 3, day : 21, hour : i})
    if(stats) {
        print(i   ': '   stats.views   ' views')
    } else {
        print(i   ': no hits')
    };
}
  

В зависимости от того, какие аспекты вы хотите отслеживать, вы можете рассмотреть возможность добавления дополнительных коллекций (например, коллекции для отслеживания, ориентированного на пользователя). Надеюсь, это поможет.

Смотрите также

Сообщение в блоге об аналитических данных

Комментарии:

1. Интересно, как выглядел бы синтаксис find (), если бы я хотел отобразить количество просмотров для ‘Hello’ за каждый час за прошедший день?

2. .. тогда это решение было бы не совсем идеальным. Но подождите, я опубликую обновление.

3. Тем временем вы, возможно, захотите взглянуть на cookbook.mongodb.org/patterns/unique_items_map_reduce

4. И последнее, прежде чем я заткнусь: MongoDB предоставит вам скорость и гибкость для экспериментов с различными подходами. Не думайте слишком много, взломайте, посмотрите, соответствует ли это вашим потребностям, и измените его, если это не соответствует 🙂

5. Будьте очень осторожны при выполнении запросов к составным индексам (это потребуется здесь): «Если в запросе присутствует первый ключ индекса, этот индекс может быть выбран оптимизатором запросов. Если первый ключ отсутствует в запросе, индекс будет использоваться только при явном указании. Хотя индексы могут использоваться во многих случаях, когда в запросе присутствует произвольное подмножество индексированных полей, как правило, оптимальными индексами для данного запроса являются те, в которых запрашиваемые поля предшествуют любым не запрашиваемым полям.» mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeysIndexes

Ответ №2:

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

Следует помнить о том, что если вы продолжаете обновлять документ, его размер будет расти, а это означает, что Mongo в конечном итоге потребуется найти для него новое место в индексе. Если у вас обновляется много документов, размер которых увеличивается, Mongo потребуется многократно копировать эти документы, это может значительно замедлить работу. Конечно, все зависит от того, какой объем трафика вы ожидаете.

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