В общем, такой размер не является маленьким и для промышленных СУБД, требуя дополнительных усилий в проектировании, реализации, настройке и поддержке. Но пикантность ситуации состояла в том, что база данных была организована в виде двоичных файлов собственного формата.
Признаюсь, последний раз я видел такой подход в далёком 1994 году, когда мы переводили паспортные столы Санкт-Петербурга с подобных плоских файлов на прогрессивный по тем временам и, что важнее, открытый формат DBF под Clipper и FoxPro для MS-DOS и Novell-серверов. С оговорками перехода от флоппи-нет [115] на каналы удалённой связи, многие паспортные службы долгое время продолжали в этой системе работать, характерные алфавитно-цифровые экраны в DOS-окошке я наблюдал уже в начале 2000-х годов.
В долговременной памяти всплыли воспоминания случаев необходимости ручного декодирования форматов. К великому счастью, программисты системы не занимались тогда «эволюционной» разработкой, а знали область, в которой работают, и добросовестно поддерживали проектную документацию в актуальном состоянии. Кроме возможности прочитать собственно об устройстве системы, все описания форматов двоичных файлов также были на месте. Возникший было тёмный призрак индустриальной археологии растворился в лучах взошедшего солнца.
Поскольку в нашу задачу входило предпроектное обследование, начались интересные опыты с технологиями новыми. Начали с прототипа конвертера, извлекающего данные из старых форматов и распределяющего их по таблицам промышленной СУБД, в качестве которой выступал SQL Server. Логично было бы написать такой прототип на C++ или другом языке с возможностями прямого доступа к памяти на уровне битов, но ввиду планируемой общей разработки исключительно на C# необходимо было оценить соответствующую программу в ипостаси распаковщика байтов.
Быстро выяснилось, что побитовые операции с типами данных разной длины не являются сильным местом языка и платформы в целом. Как, например, задать ushort или вообще любую константу в двоичном виде? Никак. А ushort в шестнадцатеричном? Тоже никак, константа определяется как int, все остальные преобразования надо делать в небезопасном контексте unchecked(). В итоге код достаточно простого алгоритма пестрел вот такими вставками, которые, на минуточку, суть рекомендуемые практики. Нас настигла расплата за автоматическое управление памятью.
Convert. ToUInt32 ("00110000", 2 ); unchecked((ushort) 0xC0);
Вторым пунктом была собственно база данных. На логическом уровне структура для тестируемого случая никаких сложностей не представляла: одна узкая длинная таблица, связанная с несколькими короткими справочниками, практически «звезда», но в режиме постоянного добавления пачек новых записей. Трудность представлял собой уровень физический. Втиснуть число-признак, кодируемое тремя битами, в те же три бита на уровне СУБД стандартные средства не позволят. Минимальный размер – байт. Использовать нестандартные битовые поля в принципе можно, но тогда мы лишимся поддержки ссылочной и прочей целостности, возможности использовать SQL для выборок без переупаковки значений в битовые структуры и фактически будем использовать СУБД в качестве продвинутого аналога файлового хранилища с улучшенными функциями администрирования.
Поскольку целью было упрощение работы с пользовательскими запросами, то лишать их доступа к данным посредством прямого и понятного человеку SQL было решительно невозможно. При использовании минимальных по размеру стандартных типов данных прогнозируемый размер базы данных без учёта дополнительных индексов превысил 6 терабайт, то есть минимум удвоился по сравнению с двоичными файлами. Сжатие данных несколько скрасило ситуацию, полученные 4,5 терабайта выглядели уже неплохо. За всё надо платить, в том числе за стандартность доступа и представления данных.
Третьим пунктом была загрузка данных из C#-приложения в базу данных. Поскольку интенсивность вставки из прибывающих от датчиков текстовых файлов составляла почти 400 тысяч записей каждые 10 минут, то, разумеется, приложение должно было справляться с этой задачей за меньшее время. Оптимальной, как и следовало ожидать, оказалась пакетная загрузка, игнорирующая ограничения целостности РСУБД. Такова обычная цена компромисса.
Что имеем по итогам более чем 10-летнего развития технологий? Появилась возможность стандартизировать хранение и доступ к большому массиву данных, используя вполне обычное серверное оборудование корпоративного класса и 64-разрядную промышленную СУБД. Возникла необходимость переделывать программное обеспечение из-за утраты поддержки среды разработки поставщиком и соответствующих компетенций на рынке труда.Но я совсем не уверен, что ещё через 10 лет новые подрядчики, вынужденные в очередной раз переписывать систему, найдут документацию в том же полном виде, в котором нашли её мы. Если вообще найдут хоть что-то, кроме кода, остатков презентаций и наших отчётов.
«Оптисток», или распределённый анализ данных
Название «Оптисток» придумал уже позже кто-то из маркетинговой команды. Поль, руководитель проекта и ответственный за функционал, был первое время недоволен, так как предыдущая версия продукта называлась «Оскар». Поэтому корневой директорий системы так и живёт до сих пор под названием Oscar2.
Организация процесса получилась близкой к подходу MSF, но с учётом относительно небольшого масштаба. Из рабочих групп оставалось, с одной стороны, только управление продуктом, совмещённое с управлением проектом, где кроме Поля были задействованы ключевые пользователи и представитель директората. С другой – была объединённая группа архитектуры и разработки за моей ответственностью и основным участием вкупе с координацией привлекаемых к проекту специалистов по SAP, корпоративному хранилищу данных и графике. Спираль процессов потребовала всего полторы фазы с одним прототипом.
С оговорками, я работаю в такой организации со студенческих времён и считаю её наиболее эффективной и комфортной для разработки продукта или заказного проекта. Опыт Microsoft показывает хорошие возможности масштабирования процесса. Но мы ещё вернёмся к этому вопросу.
Если применить к «Оптистоку» действующие классификации, то это система класса SFA (Sales Forces Automation – автоматизация продаж на выезде), предназначенная для выстраивания каналов сбыта, ориентированных на конкретного клиента. Рынок – автомобильные компоненты, запчасти и тому подобное. С другой стороны, система занимается аналитической обработкой данных и относится к BI. Типовое использование проходит по следующему сценарию.
Приходит торговый агент компании к клиенту со своим ноутбуком, запускает программу, выбирает номенклатуру, параметры поиска и ограничения, задаёт целевые ориентиры, например, увеличение продаж по данной продуктовой линии на 5 % при складской политике «запас на 7 недель», выбирает географию продаж клиента и запускает расчёт. В итоге получается прогноз-анализ на основе оценки:
• продаж компании в выбранной географии. Например, данные отгрузки по стране клиента;
• парка автомобилей выбранного сегмента рынка, также с учётом географии. Например, вся Голландия или только 75-й департамент Франции.
После чего клиенту предлагается пополнить склад некоторым количеством товаров на базе этих расчётов.
Архитектура подобных систем, можно сказать, типовая. Проектируем специализированное хранилище, ищем в корпоративной среде источники нужной информации, организуем регулярное обновление данных, предоставляем пользователям интерфейс для доступа к данным: непосредственно к хранилищу или к так называемым витринам ( datamart ) и кубам. Наибольшую трудность, кстати, вызывает не сам импорт данных, а поиск в компании людей, которые могут знать, где эти данные взять. Всё-таки 20 тысяч таблиц SAP R3 и примерно столько же в корпоративном хранилище – не шутка, поэтому без хороших проводников раскопки источников информации обернутся поиском иголки в стоге сена.