Формирование данных о пользовательских сессиях на основе журнальных файлов Web-сайтов
При анализе посещений пользователями Web-сайтов распространенной аналитической задачей является разделение посещений ("кликов") данного пользователя на сессии. Сессия – это некоторый период активности пользователя на Web-сайте. В сессию включаются все клики пользователя, произведенные им в заданный период времени. На рис. 2 демонстрируется разбиение на сессии таблицы кликов. Эта простая таблица кликов содержит только временную метку (timestamp) клика и идентификатор пользователя (userid), ассоциированный с данным кликом. В результирующей таблице (рис. 2b), которая для наглядности разделена по userid, каждая пара кликов, время между которыми меньше 60 секунд, считается входящей в одну и ту же сессию.
Рис. 2. Пример разбиения кликов на сессии: в таблице (a) содержатся необработанные данные о кликах, а в таблице (b) клики сгруппированы по userid, и в строки добавлен номер сессии; сессии формируются на основе временного интервала в 60 секунд.
Разбиение на сессии можно выполнить с использованием SQL, но SQL/MR позволяет упростить это действие и повысить его эффективность. В SQL/MR-функции для этого разбиения требуется только один проход по таблице кликов, в то время как при выполнении SQL-запроса потребуется дорогостоящее соединение этой таблицы с ней же самой. Кроме того, динамический полиморфизм SQL/MR-функции позволяет повторно использовать ее для вычисления информации о сессиях над таблицами с любой схемой. Таким образом, SQL/MR-функция для разбиения на сессии становится повторно используемой библиотечной подпрограммой, которую может использовать любой аналитик.
Сначала мы покажем использование SQL/MR-функции sessionize в запросе над таблицей кликов с рис. 2, а потом опишем реализацию самой функции.
Рис. 3. Использование в запросе вызова SQL/MR -функции sessionize.
На рис. 3 показано использование SQL/MR-функции sessionize в запросе над таблицей кликов. Мы производим разделение таблицы по userid, чтобы сгруппировать клики каждого пользователя.
Затем каждый раздел упорядочивается по временным меткам. Имеются два раздела специальных аргументов: TIMECOLUMN и TIMEOUT. Во время инициализации раздел аргумента TIMECOLUMN указывает, какой атрибут входной таблицы будет анализироваться для определения принадлежности к сессии. Также сохраняется и значение аргумента TIMEOUT, так что оно может использоваться во время выполнения для определения того, не обнаружена ли граница какой-либо сессии. Во время инициализации SQL/MR функция sessionize также определяет свою результирующую схему, как схему входной таблицы, к которой добавлен атрибут session целого типа. Такое поведение позволяет использовать SQL/MR-функцию sessionize при любой схеме входной таблицы. Для достижения еще большей гибкости можно было бы добавить третий собственный раздел аргумента OUTPUTALIAS. Тогда во время выполнения пользователь мог бы указать имя нового столбца таблицы сессий.
Реализация SQL/MR-функции sessionize очень проста. Она реализуется как функция над разделами, при вызове которой входная таблица разделяется по значениям атрибута, определяющего, чьи сессии мы хотим выявлять, например, userid. Внутри каждого раздела входные данные должны быть упорядочены по значениям атрибута, определяющего границы сессий, например, ts. Для каждого обработанного раздела счетчик сессий инициализируется нулем. За один проход по каждому разделу SQL/MR-функция sessionize сравнивает значения TIMECOLUMN соседних кортежей для определения того, не превышает ли разность этих значений заданное значение TIMEOUT. Если не превышает, то для обоих кортежей в номер сессии заносится текущее значение счетчика сессий, иначе счетчик сессий увеличивается на единицу, и номеру сессии кортежа с большим значением TIMECOLUMN присваивается новое значение счетчика. Исходный код этой функции показан в подразделе 3.3, в котором описывается интерфейс программирования SQL/MR.