1. Зачем анализировать ODI через SQL-запросы
Работая с Oracle Data Integrator (ODI), мы ценим его графический интерфейс за автоматизацию рутины и удобство разработки. Однако, когда проект масштабируется до десятков пакетов и сотен сущностей, GUI перестает быть оптимальным инструментом для отслеживания потоков данных, глубокого анализа и аудита зависимостей.
В таких случаях ключом к эффективности становится прямое взаимодействие с метаданными ODI через SQL-запросы к его репозиториям. Эта статья посвящена именно этому – практической работе со структурой репозиториев ODI и детальному разбору SQL-запроса для построения потоков данных.
Мы разберем:
-
Архитектуру репозиториев ODI: Master и Work.
-
Ключевые таблицы метаданных, их структуру и взаимосвязи.
-
Практический пример SQL-запроса.
Поскольку информация в сети часто разрознена, я собрала здесь ключевые сведения о структуре репозиториев, основные таблицы и рабочий пример запроса для анализа маппингов.
Примечание:
Все примеры и запросы в данной статье основаны на Oracle Data Integrator Studio версии 12.2.1.4.201001 с версией репозитория 05.02.02.07. Структура метаданных может изменяться между версиями ODI. Также следует учесть, что схемы репозиториев (ODI_WORK, ODI_MASTER) могут называться иначе.
2. Репозиторий
Ключ к пониманию ODI лежит в его архитектуре, разделенной на репозитории.
Архитектура ODI предполагает наличие одного Master репозитория и одного или нескольких Work репозиториев. В некоторых случаях (например, при географически распределенной разработке) и Master репозиториев может быть несколько.
Давайте разберем чем отличается Master от Work репозитория.
Master Repository
Хранит глобальные данные, не привязанные к конкретному проекту. В основном это информация со вкладки Topology.
Хранит обычно общую информацию:
-
Топология (SNP_TOPOLOGY, SNP_CONNECT, SNP_PSCHEMA, SNP_CONTEXT).
-
Пользователи (SNP_USER).
-
Языки программирования (SNP_LANG).
Зачем нужен: Администрирование сред, безопасности и управление логическими и физическими подключениями.
Ниже на изображении отмечены ключевые сущности топологии и соответствующие им таблицы в репозитории:

Пример запроса:
select pc.I_context, pc.I_lschema, pc.I_pschema, c.context_name, p.EXT_NAME, l.LSCHEMA_NAME, t.TECH_INT_NAME, t2.TECH_INT_NAME from ODI_MASTER.SNP_PSCHEMA_CONT pc join ODI_MASTER.snp_context c on (c.I_context=pc.I_context) join ODI_MASTER.SNP_LSCHEMA l on (l.i_lschema = pc.i_lschema) join ODI_MASTER.SNP_PSCHEMA p on (p.I_PSCHEMA = pc.I_PSCHEMA) join ODI_MASTER.SNP_TECHNO t on (t.I_TECHNO = l.I_TECHNO) join ODI_MASTER.SNP_CONNECT cn on (cn.I_CONNECT = p.I_CONNECT) join ODI_MASTER.SNP_TECHNO t2 on (t2.I_TECHNO = cn.I_TECHNO) where c.context_name = 'DEV' and p.EXT_NAME = 'Cluster DWH Hive.default' and l.LSCHEMA_NAME = 'default'

Work Repository
Хранимую информацию можно разделить на 2 части, которые хранятся в одной схеме. Первая обычно называется «Work» и хранит данные со вкладки Operator (runtime данные), а вторая – «Designer» и хранит данные со вкладки Designer, т.е. хранится все, что связано с процессом разработки. Такое разделение Work и Design помогает ориентироваться в официальной документации и быстрее находить нужные объекты в интерфейсе.
Что хранит Work:
-
Логи выполнения, запуски, статусы и шаги выполнения (SNP_SESSION, SNP_SESS_TASK, SNP_STEP_LOG).
-
Переменные, которые используются во время выполнения в сценарии (SNP_VAR_SESS, SNP_VAR_SCEN)
-
Сценарии и их шаги (SNP_SCEN, SNP_SB_STEP, SNP_SB_TASK)
-
Модули Знаний / Knowledge Modules (SNP_TRT)
Зачем нужен: Мониторинг выполнения, отладка, анализ производительности и ошибок.
Что хранит Designer:
-
Проекты и папки (SNP_PROJECT, SNP_FOLDER)
-
Пакеты, маппинги (SNP_PACKAGE, SNP_MAPPING)
-
Модели данных, переменные (SNP_MODEL, SNP_VAR)
Зачем нужен: Анализ кода, поиск зависимостей, рефакторинг, документирование проектов.
На скриншоте показано соответствие объектов интерфейса, таких как проекты и модели, таблицам в work репозитории:

3. Главные объекты репозитория ODI и их структура
Все объекты в ODI связаны и образуют иерархию. Понимание этих связей — ключ к написанию осмысленных запросов.
Например, маппинг (SNP_MAPPING) или пакет (SNP_PACKAGE) всегда находится в папке (SNP_FOLDER), которая принадлежит проекту (SNP_PROJECT).
Когда генерируется сценарий (SNP_SCEN) из маппинга, он становится готовым к выполнению кодом. Каждый его запуск создает сессию (SNP_SESSION), которая состоит из шагов (SNP_SESS_STEP) и задач (SNP_SESS_TASK).
Общие элементы многих таблиц:
-
SNP_<OBJECT> — основные таблицы
-
OGG_<OBJECT> — таблицы Oracle Golden Gate
-
<OBJECT>_NO или I_<OBJECT> — уникальный идентификатор объекта. Например, I_MAPPING для маппингов или SESS_NO для сессий.
-
<OBJECT>_NAME — Название объекта, текстовый идентификатор.
Как правило, это внутреннее имя объекта в репозитории. В то время как оно часто совпадает с отображаемым, для некоторых объектов имя в GUI хранится в других полях. Например, для физической схемы — EXT_NAME. -
Поле GLOBAL_ID — Уникальный глобальный идентификатор объекта.
Вот несколько примеров:
|
Объект |
Таблица |
ID |
Имя |
Ключевые связи |
|
Проекты |
SNP_PROJECT |
I_PROJECT |
PROJECT_NAME |
|
|
Папки |
SNP_FOLDER |
I_FOLDER |
FOLDER_NAME |
I_PROJECT (к проекту), PAR_I_FOLDER (к родительской папке) |
|
Маппинги |
SNP_MAPPING |
I_MAPPING |
NAME |
I_FOLDER (к папке) |
|
Сценарии |
SNP_SCEN |
SCEN_NO |
SCEN_NAME |
Может содержать I_MAPPING, I_PACKAGE и т.д., в зависимости от источника |
|
Сессии |
SNP_SESSION |
SESS_NO |
SESS_NAME |
SCEN_NO (к сценарию), I_CONTEXT (к контексту) |
|
Задачи сессии |
SNP_SESS_TASK |
I_SESS_TASK |
TASK_NAME1 |
SESS_NO (к сессии) |
4. Запрос для анализа потоков данных
Этот запрос позволит построить карту потоков данных, которые «протекают» через маппинги. Он не только определяет таблицы-источники и таблицы-цели для всех маппингов, но и обогащает эти данные информацией о физическом расположении – вплоть до JDBC URL серверов, на которых эти таблицы находятся.
Код запроса
with PROJECT_FOLDER -- то, где хранится маппинг на вкладке Designer в разделе Projects as (select PROJECT_NAME, PROJECT_NAME || '/' || case when f2.FOLDER_NAME is not null then f2.FOLDER_NAME || '/' || f1.FOLDER_NAME else f1.FOLDER_NAME end PathFolder, nvl(f1.i_folder, f2.i_folder) i_folder from ODI_WORK.SNP_PROJECT join ODI_WORK.SNP_FOLDER f1 on (f1.I_PROJECT = SNP_PROJECT.I_PROJECT) left join ODI_WORK.SNP_FOLDER f2 on (f2.I_PROJECT = f1.PAR_I_FOLDER)), models as (select SNP_MODEL.TECH_INT_NAME, SNP_MODEL.LSCHEMA_NAME, snp_table.res_name, COD_MOD, SNP_MODEL.COD_MOD || '.' || snp_table.res_name as QUALIFIED_NAME, SNP_MODEL.REV_CONTEXT, I_TABLE from ODI_WORK.SNP_MODEL -- Модели. Расположение Designer/Models join ODI_WORK.SNP_TABLE on (SNP_TABLE.I_MOD = SNP_MODEL.I_MOD)) select PROJECT_FOLDER.PROJECT_NAME, PROJECT_FOLDER.PathFolder, SNP_MAPPING.NAME, case when SNP_MAP_CONN_ie.name is not null and SNP_MAP_CONN_os.name is null then 'target' when SNP_MAP_CONN_ie.name is null and SNP_MAP_CONN_os.name is not null then 'source' end src_trg, nvl(models_rf.TECH_INT_NAME, models_qn.TECH_INT_NAME) as TECH_INT_NAME, nvl(models_rf.LSCHEMA_NAME, models_qn.LSCHEMA_NAME) as LSCHEMA_NAME, SNP_PSCHEMA.EXT_NAME as PSCHEMA_NAME, nvl(models_rf.res_name, models_qn.res_name) as res_name, SNP_CONTEXT.CONTEXT_NAME, SNP_CONNECT.CON_NAME, SNP_CONNECT.DSERV_NAME, case SNP_CONNECT.CONNECT_TYPE when 'D' then 'User Defined' when 'R' then 'Repository' when 'H' then 'Hadoop' when 'P' then 'Pig' when 'I' then 'Hive' when 'B' then 'HBase' when 'K' then 'Kafka' when 'S' then 'Spark Python' else SNP_CONNECT.CONNECT_TYPE end as Data_Server, TO_CHAR(DBMS_LOB.SUBSTR(SNP_MTXT.FULL_TXT)) as URL from ODI_WORK.SNP_MAPPING inner join PROJECT_FOLDER on (PROJECT_FOLDER.I_FOLDER = SNP_MAPPING.I_FOLDER) inner join ODI_WORK.SNP_MAP_COMP on (SNP_MAP_COMP.I_OWNER_MAPPING = SNP_MAPPING.I_MAPPING) inner join ODI_WORK.SNP_MAP_REF on (SNP_MAP_REF.I_MAP_REF = SNP_MAP_COMP.I_MAP_REF) left join models models_rf on (SNP_MAP_REF.I_REF_ID is not null and models_rf.I_TABLE = SNP_MAP_REF.I_REF_ID) left join models models_qn on (models_rf.I_TABLE is null and models_qn.QUALIFIED_NAME = SNP_MAP_REF.QUALIFIED_NAME) left join ODI_WORK.SNP_MAP_CP SNP_MAP_CP_i on (SNP_MAP_CP_i.I_OWNER_MAP_COMP = SNP_MAP_COMP.I_MAP_COMP and SNP_MAP_CP_i.DIRECTION = 'I') left join ODI_WORK.SNP_MAP_CONN SNP_MAP_CONN_ie on (SNP_MAP_CONN_ie.I_END_MAP_CP = SNP_MAP_CP_i.I_MAP_CP) left join ODI_WORK.SNP_MAP_CP SNP_MAP_CP_o on (SNP_MAP_CP_o.I_OWNER_MAP_COMP = SNP_MAP_COMP.I_MAP_COMP and SNP_MAP_CP_o.DIRECTION = 'O') left join ODI_WORK.SNP_MAP_CONN SNP_MAP_CONN_os on (SNP_MAP_CONN_os.I_START_MAP_CP = SNP_MAP_CP_o.I_MAP_CP) left join ODI_MASTER.SNP_CONTEXT on (SNP_CONTEXT.context_code = nvl(models_rf.REV_CONTEXT, models_qn.REV_CONTEXT)) -- в норме быть значение из планировщика с которым запускается маппинг left join ODI_MASTER.SNP_LSCHEMA ON (SNP_LSCHEMA.LSCHEMA_NAME = nvl(models_rf.LSCHEMA_NAME, models_qn.LSCHEMA_NAME)) left join ODI_MASTER.SNP_PSCHEMA_CONT ON (SNP_PSCHEMA_CONT.I_CONTEXT = SNP_CONTEXT.I_CONTEXT AND SNP_PSCHEMA_CONT.I_LSCHEMA = SNP_LSCHEMA.I_LSCHEMA) left join ODI_MASTER.SNP_PSCHEMA ON (SNP_PSCHEMA.I_PSCHEMA = SNP_PSCHEMA_CONT.I_PSCHEMA) left join ODI_MASTER.SNP_CONNECT ON (SNP_CONNECT.I_CONNECT = SNP_PSCHEMA.I_CONNECT) left join ODI_MASTER.SNP_MTXT ON (SNP_MTXT.I_TXT = SNP_CONNECT.I_TXT_JAVA_URL AND SNP_MTXT.I_TXT_ORIG = 6) where SNP_MAPPING.name = 'map_Smpl_fromHive_toOracle_overSqoop' -- находим нужный маппинг and SNP_MAP_COMP.TYPE_NAME in( 'DATASTORE', 'FILE')-- нам нужны только таблицы and not (SNP_MAP_CONN_ie.name is not null and SNP_MAP_CONN_os.name is not null) -- исключаем промежуточные таблицы src->TMP->trg order by 1,2,3;
Диаграмма запроса

Детальный разбор запроса
Давайте разберем его по частям на примере маппинга map_Smpl_fromHive_toOracle_overSqoop:

Результат работы запроса в файле и на скриншоте (разбит на две части):


with PROJECT_FOLDER as (…)
Этот блок кода собирает полный путь к папке, где хранится маппинг. Запрос объединяет имя проекта (PROJECT_NAME) с именем родительской папки (f2.FOLDER_NAME) и дочерней папки (f1.FOLDER_NAME), если они существуют.
Для маппинга map_Smpl_fromHive_toOracle_overSqoop FOLDER_NAME — «EXAMPLES/Hive», а PROJECT_NAME – «EXAMPLES».
models as (…)
Здесь собирается информацию о моделях данных и таблицах, которые в них содержатся. В нашем случае две таблицы smlp_data_tbl (hive) и SMLP_DATA_TBL (oracle).

select SNP_MODEL.TECH_INT_NAME, SNP_MODEL.LSCHEMA_NAME, snp_table.res_name, COD_MOD,SNP_MODEL.COD_MOD ||'.'||snp_table.res_name as QUALIFIED_NAME , SNP_TABLE.I_TABLE from ODI_WORK.SNP_MODEL -- Модели. Расположение Designer/Models join ODI_WORK.SNP_TABLE on (SNP_TABLE.I_MOD = SNP_MODEL.I_MOD) where (snp_table.res_name = 'smlp_data_tbl' and SNP_MODEL.COD_MOD ='HADOOP_DEFAULT') or (snp_table.res_name ='SMLP_DATA_TBL' and SNP_MODEL.COD_MOD = 'PUB_DS_SAMPLES')
В основном запросе models подключается дважды (models_rf и models_qn). Это сделано для надежности. Сначала идет попытка соединения по идентификатору (I_REF_ID), так как это наиболее точный способ. Если эта связь не найдена, то запрос пытается найти соответствие по полному квалифицированному имени (QUALIFIED_NAME). Если и после этого информация о модели не найдена, вероятно, она была удалена, и в интерфейсе ODI такой элемент будет помечен как «Deleted».

QUALIFIED_NAME
SNP_MODEL.COD_MOD ||'.'||snp_table.res_name as QUALIFIED_NAME
Здесь создается уникальное полное имя для каждой таблицы, объединяя код модели и имя ресурса. Это имя используется для связи с маппингами по условию (models.QUALIFIED_NAME = SNP_MAP_REF.QUALIFIED_NAME).
left join ODI_WORK.SNP_MAP_COMP … left join ODI_WORK.SNP_MAP_REF
Данный набор соединений связывают маппинг с его компонентами (SNP_MAP_COMP) и ссылками на объекты (SNP_MAP_REF).
Довольно важным элементов здесь является фильтр SNP_MAP_COMP.TYPE_NAME in (‘DATASTORE’, ‘FILE’). Таблица SNP_MAP_COMP хранит все компоненты, которые можно увидеть на диаграмме маппинга. Для построения потоков данных нас интересуют только те компоненты, которые представляют собой внешние сущности:
-
DATASTORE – это таблицы и представления в базах данных, т.е. модели данных.
-
FILE – это буквально файлы (CSV, TXT и тд)
Остальные многочисленные типы компонентов, такие как JOIN, FILTER, EXPRESSION, AGGREGATE, представляют собой операции преобразования данных внутри маппинга.
Ещё есть компонент REUSABLEMAPPING. Компонент с таким типом представляет собой вложенный маппинг (reusable mapping). В данном запросе он не обрабатывается отдельно, так как его источники и приемники будут корректно отображены при анализе самого вложенного маппинга как отдельный маппинг.
left join ODI_WORK.SNP_MAP_CP … left join ODI_WORK.SNP_MAP_CONN
Здесь мы присоединяем коннекторы (SNP_MAP_CONN) и их точки (SNP_MAP_CP), чтобы отследить направление потока данных (DIRECTION=’I’ для входящего, DIRECTION=’O’ для исходящего).
Как выглядит содержимое таблицы ODI_WORK.SNP_MAP_CP для маппинга map_Smpl_fromHive_toOracle_overSqoop:

select cp.*, t.name as COMP_TYPE from ODI_WORK.SNP_MAP_CP cp left join ODI_WORK.SNP_MAP_CP_ROLE r on (r.I_MAP_CP_ROLE = cp.I_MAP_CP_ROLE) left join ODI_WORK.SNP_MAP_COMP_TYPE t on (t.I_MAP_COMP_TYPE=r.I_OWNER_COMP_TYPE) where cp.I_map_cp in (199434,199435,199436,199439, 199437, 199438);
where SNP_MAPPING.name = ‘map_Smpl_fromHive_toOracle_overSqoop’) — фильтр для выбора конкретного маппинга по имени из интерфейса.
and not(SNP_MAP_CONN_ie.name is not null and SNP_MAP_CONN_os.name is not null) — это условие исключает промежуточные таблицы, у которых есть как входящие, так и исходящие потоки в рамках одного компонента.
В интерфейсе такая таблица выглядит следующим образом:

case when … then ‘target’ when … then ‘source’ end src_trg
В данной строке с помощью анализа связей в SNP_MAP_CONN (таблица, описывающая потоки данных), запрос определяет, является ли таблица источником (‘source’) или целевой (‘target’).
Считаем, что если есть «input connection point» и нет «output connection point», то это целевая таблица.
А если есть «output connection point» и нет «input connection point», то это источник.

left join ODI_MASTER.SNP_CONTEXT
Эта таблица используется для задания контекста. Для определения контекста используется поле REV_CONTEXT из модели данных. Это контекст, который по умолчанию используется для реверс-инжиниринга.
Важный момент:
Для демонстрации этого достаточно, но в реальном проекте для точного анализа контекст выполнения следует брать из данных о фактическом запуске (например, из таблицы SNP_SESSION) или из параметров внешнего планировщика.
SNP_LSCHEMA → SNP_PSCHEMA_CONT → SNP_PSCHEMA → SNP_CONNECT — эта цепочка подключений является преобразованием логической схемы в физическую (конкретная схема на сервере) в рамках заданного контекста.
left join ODI_MASTER.SNP_MTXT ON (SNP_MTXT.I_TXT = SNP_CONNECT.I_TXT_JAVA_URL AND SNP_MTXT.I_TXT_ORIG = 6)
В данном подключение извлекается текстовое значение URL. Условие I_TXT_ORIG = 6 — это строго определенный в ODI идентификатор, который говорит, что извлекаемый текст является именно «JDBC URL для сервера данных». Вот несколько примеров других значений:
-
1 (SNP_ACTION.I_TXT_DESC)
-
9 (SNP_VERSION.I_TXT_VERSION_COMMENT)
-
16 (SNP_TECHNO.I_FK_TXT)
-
7 (SNP_CONNECT.I_TXT_JNDI_URL)
-
12 (SNP_CONNECT.I_TXT_WS_BASE_URL)
-
13 (SNP_USER.I_TXT_DETAIL)
В итоге запрос предоставляет не просто логическую карту маппинга, а полную картину потока данных: от расположения в проекте до конкретных URL. Это полезно для анализа сетевых взаимодействий и документирования систем.
5. Заключение
Прямой доступ к таблицам репозиториев ODI через SQL — это не замена графическому интерфейсу, а мощный аналитический инструмент для решения нетривиальных задач. Представленный в статье запрос является тому подтверждением и решает ключевую проблему в управлении данными — построение поток данных для маппингов от логического объекта в проекте до физического URL сервера баз данных.
Такой подход позволяет проводить аудит системных интеграций и автоматически генерировать документацию.
Освоение прямого доступа к метаданным ODI открывает путь к более глубокому контролю и пониманию ETL-процессов.
6. Полезные материалы
-
Статья посвящена работе с метаданными репозитория — https://www.clearpeaks.com/odi-11g-repository-metadata-tips-tricks/ . Это хороший ресурс для понимания структуры репозитория, поэтому он выделен в отдельный пункт.
-
Другие запросы
-
Набор полезных SQL-запросов к репозиторию ODI. Запросы предназначены для административных задач и управления, например, для поиска сессий с ошибками, анализа запущенных сценариев и получения списков объектов: https://gist.github.com/rmorenobello/0d8add698f70c53020665faf9b813a27
-
В статье приводится и объясняется SQL-запрос, который позволяет извлечь из репозитория точный код (например, SQL), который был выполнен в рамках конкретного шага сессии ODI – https://devepm.com/2020/02/26/odi-hidden-gems-snp-tables-query-to-get-executed-code-example/
-
Статья предоставляет SQL-запросы для получения детальной информации о выполнении планов загрузки, включая статусы отдельных шагов, время их выполнения и последовательность – https://devepm.com/2022/12/06/odi-hidden-gems-snp-tables-query-to-get-load-plan-execution-steps/
-
-
oracle.com
-
Документация: https://docs.oracle.com/en/middleware/fusion-middleware/data-integrator
И, в частности, про репозитории: https://docs.oracle.com/middleware/12211/odi/administer-develop/admin_reps.htm -
Сообщество: https://forums.oracle.com/ords/apexds/domain/dev-community?tags=oracle-data-integrator
-
ссылка на оригинал статьи https://habr.com/ru/articles/936088/
Добавить комментарий