Совершенно не могу работать в проектах, где не я архитектуру/дизайн разрабатывал и/или одобрял. Замечаю такое количество ошибок, что просто отворачивает сразу и надолго. Когда в такой проект попадаешь, как-то не вяжется с тем, что уже вроде как 2009 год. Старость, что-ли?
Вот, например, текущий проект. Множество ETL трансформаций перерабатывает данные от различных торговых систем банка. Трансформация стартуют в тот момент, когда внешняя система публикует очередной снимок своего состояния в виде CSV файла или в Oracle view. Переработанные данные складываются в гигантскую базу на основе Oracle, где хранятся на протяжении нескольких лет.
Соответственно, хаотический подход к проектированию породил зверя, у которого трансформации конфигурируются через базу данных, планировщик, их запускающий, написан на Java, а сами трансформации по большей части на PL/SQL. Типичная трансформация работает так: планировщик обнаруживает новую версию файла и запускает SQL Loader. Loader заливает данные в нелогируемую и неархивируемую таблицу. Далее планировщик запускает хранимую процедуру валидации, которая проверяет, что нет повторений и все важные поля не пусты. После этого он выполняет другую процедуру, которая перемещает данные в основную логируемую и архивируемую таблицу, где данные остаются жить на веки вечные. Следующий и последний шаг, который исполняется планировщиком также путем вызова хранимки, - формирование и рассылка событий с помощью OracleAQ.
Что и почему мне категорически не нравится в имплементации? Попробую раскрыть подробнее:
Планировщик
Что есть:
практически единственный, жестко-фиксированный тип задания, который он может обработать - проверить, есть ли новый снимок и запустить трансформацию из фиксированного набора шагов (см. выше). Конфигурировать можно то, какие хранимки вызываются, но их набор ограничивается структурой таблицы, а порядок вызова - джавовским обработчиком.
Что наблюдаем:
помимо оригинального требования к обработке файлов от внешних систем появились новые - импорт из view, автономный периодический экспорт своего состояния, etc. Всё новое в существующую схему БД вписывается очень криво, многие поля начинают трактоваться по-иному, в зависимости от типа задания.
Должно быть:
гибкий планировщик с персистентностью, безразличный к реализации выполняемых задач. Планировщик должен уметь регулярно или однократно запускать задачу, продвигать задачу из состояния в состояния, сохранять его при необходимости, иметь четко выраженный интерфейс управления и мониторинга. Фактически, persisting workflow manager.
Конфигурацию для задания также как и его состояние вовсе не обязательно размазывать по туче таблиц. Можно хранить в виде XML или JSON.
Трансформации
Что есть:
Куча однотипных PL/SQL процедур, которые варьируются в зависимости от внешней системы, откуда происходит импорт. Используются составные ключи из трех компонент: тип задачи, версия данных и дата обработки.
Что наблюдаем:
Огромное количество copy-paste кода с крайне ограниченным повторным использованием, без намека на юнит-тесты.Не говоря уже о том, что PL/SQL выглядит крайне убого и угрожающе громоздко в тех случаях,когда требуется найти дупликаты или обнаружить пропущенные значения.(PL/SQL вообще недоязык какой-то - длина идентификатора ограничена 30 символами, пространств имен нет, набор функций крайне ограниченный,разбиение пакетов на спецификацию и тело живо напоминает о всех сходных неудобствах с++; в общем - откровенное старьё).
Проблемы управления экземпляром Оракла, где постоянно на больших объёмах данных происходит переполнение архивного лога. Вопрос скорее организационный, но, зная тормознутость местных админов, нужно было это предвидеть и учесть в архитектуре.
Следует использовать однокомпонентные ключи хотя бы для того, чтобы избежать необходимости повторять набор параметров в процедурах. Тем более, что наиболее часто встречающаяся комбинация из нескольких компонент [тип, версия, дата], скорее всего, идентифицирует один объект - Job (тогда описание задания будет именоваться JobTemplate).
Должно быть:
Варант 1 - нафиг Оракл, используем SQL Server и SSIS. Все трансформации конфигурируются в виде SSIS-пакеты и деплоятся как задачи в SQLServer Agent.
Кстати, SQLServer обладает серьезным преимуществом перед Ораклом в том, что возможно выполнять bulk load, используя клиентское API. В Оракле же - только sqlldr.
Вариант 2 - цепочку sql loader >> java scheduler- >> duplicate-and-null check stored proc выбрасываем. Вместо этого читаем CSV на Java, отбрасываем дупликаты, проверяем на null, и результат сохраняем в CSV-файл, который затем загружается Loader-ом в основную таблицу. Получаем важное преимущество - независимый процесс гораздо проще контролировать, чем поведение экземпляра Оракл, нагруженного обработкой больших объёмов данных. Более того, исчерпание дискового пространства также проще контролировать и исправлять проблемы, нежели управлять экземпляром Оракла при помощи местных админов.
С точки зрения производительности проведенный мной несложный тест показал, что скорость такого процессинга сравнима, если не лучше, чем в оргинальной последовательности.
[To be updated]