Моя первая аналитическая база данных
Расскажу решение одной частной задачи, которое показывает, почему для отчетности приходится обрабатывать данные за пределами рабочей базы. В данном случае вне биллинга.
Проблемы
Меняющиеся атрибуты
Потребовалось сделать отчет по остаткам на лицевых счетах в биллинге на начало и конец каждого месяца. Данные идут в бухгалтерию.
Проблема — если мы относим договор к определённому нашему юридическому лицу (их несколько в биллинге), то в будущем, если атрибуты договора (вдруг по какой-либо причине) будут изменены, все его балансы за все периоды в прошлом будут отнесены к остаткам нового юридического лица и исключены из остатков старого.
Это должно быть недопустимо, но происходит, учитывая количество людей, которые работают с данными в биллинге и качество данных, которые являются результатом ряда поглощений и миграций. В конце концов, есть люди, которые тем и занимаются, что приводят данные в порядок в то время, как странно импортированный (откуда-нибудь) абонент работает и платит (перекашивая балансы юридических лиц).
Чтоб ответить на вопрос "почему изменились цифры?", нужно иметь возможность сопоставить атрибуты договоров до и после момента предоставления отчёта.
Сложные запросы
В BG биллинге, ввиду внутренней оптимизации, могут отсутствовать балансовые записи по договору за месяц, когда движения баланса не было. В этом случае считается, что раз движение 0, входящий остаток равен исходящему, он уже отражён в предыдущей записи. Да, с учётом накопления базы бывших (не действующих) абонентов, это даёт кое-какую экономию в дисковом пространстве.
Но, чтобы строить SQL запросы по таким данным, неплохо бы их сначала привести в форму — одна балансовая запись за каждый месяц, вне зависимости от того менялся баланс или нет. Если делать это на лету, получается очень сложный запрос. Куда проще развернуть данные в виде таблицы.
Решение
С точки зрения отчета есть база, которая содержит:
- Таблица с версиями данных. Содержит № версии и дату загрузки.
- Представление атрибутов договоров. Ключ - ID договора.
- Представление балансов. Ссылается на ID договора и месяц.
Записи в таблицах под представлениями (2 и 3) ссылаются на записи таблицы версий (1), но сами представления показывают только последнюю версию.
Процесс наполнения базы выглядит так. Например, мы загружаем свежие данные 12.12.2011 в 12:05:
- В таблице с версиями данных (1) создается запись 16 с датой 12.12.2011 12:05.
- В таблицы соответствующих представлений (2 и 3) загружаются данные, где в поле номера версии записывается 16.
Отчеты делаются через представления.
Представим теперь, что отчет полученный в прошлом месяце и в этом месяце за один и тот же период отличается. Что бы ответить на вопрос "почему?", я могу сделать запрос уже к таблицам.
Преимущества
- Появляется некий способ ответа на вопрос "что изменилось?".
- Снижается нагрузка на рабочую БД сложными запросами.
- Многоэтажные подзапросы не повторяются из отчёта в отчёт, что сокращает объём отладки и упрощает изменения.
- Возможна замена исходной системы с сохранением всех старых отчётов, путём переписывания только механизма подготовки данных.
Недостатки
Оригинальная статья написана 8 декабря 2011 года, когда я ещё не прочитал нужных книг и не знал, что сделанная мною аналитическая база данных называется хранилищем данных (Data Warehouse). Недостатки дописаны 25 февраля 2017 года.
Расточительность
- Большинство договоров не изменялись между загрузками, но всё равно создавались новые записи для них.
- Ранее сформированные балансы сами по себе не должны были меняться, так как период в биллинге закрывался, хотя по необходимости это могло происходить. Но, в аналитической базе при каждой загрузке для каждого баланса за каждый месяц по каждому договору создавалить новые записи.
Именно это и послужило причиной смерти решения.
Одинаковая модель для всех атрибутов
Записи балансов за старый период были привязаны, тем не менее, к записям договоров в их последнем состоянии.
Для одной части атрибутов такая модель подходит. Например, изменение юридического лица в договоре это, бесусловно, исправление ошибки. Наверно, правильно старые балансы клиента перенести на новое юридическое лицо оператора.
Для другой части атрибутов такая модель не подходит. Например, изменение менеджера, ответственного за договор.
В классическом хранилище данных, записи измерений (аналог таблицы атрибутов в моём решении) ведут себя по разному (дублируются или модифицируются) в зависимости от того, какие именно атрибуты были изменены.
Кроме того, в классическом ХД, записи фактов (балансы), если они не менялись сами по себе, остаются привязанными к однажды выбранной записи измерения навсегда. Таким образом, если запись измерения дублируется (в связи с изменением некоторых атрибутов), старые факты могут группироваться и отбираться по старым значениям атрибутов (например, старые балансы по старым ответственным менеджерам).