
Данный материал подходит для тех сотрудников, которые не имеют опыта работы или недавно пришли на проект, связанный с хранилищами данных.
Сегодня хотим рассказать вам о рабочих буднях аналитика DWH, точнее об одной из частей этих будней. Надеемся, данное знание пригодится вам для того, чтобы быстро и без нервов освоиться на том проекте, на котором вы будете работать.
Информацию описываем вам из нашей практики работы нашего аналитика хранилищ данных.
Работу аналитика хранилищ данных можно разделить на две части:
Организация интеграции данных от какого-либо источника к какому-либо приемнику;
Поиск и решение проблем, связанных с некорректными выходными данными на приемнике, возникающих, например, в результате каких-либо технических сбоев или изменения требований к предоставляемым данным со стороны бизнеса.
В этой статье хотим с вами поговорить именно о второй части, так как, согласно практике, именно по ней отсутствует какая-либо документация по действиям для устранения каких-либо проблем.
В мире данных, где информация является ключевым активом, процессы ETL играют центральную роль в агрегации, очистке и подготовке данных для анализа и принятия решений. Однако одной из самых неприятных и критических проблем, с которой сталкиваются дата-инженеры и аналитики, является расхождение данных на приемнике (целевой системе) с данными в источнике. Как следствие, это может привести к некорректным отчетам, ошибочным бизнес-решениям и потере доверия к данным.
В статье речь пойдет об ETL-процессе, когда с источника данных «протянут» информационный поток со своей логикой преобразований, который «кладет» некорректные данные в приемник.
Самый яркий пример из моей практики – это пришедший в кредитное подразделение отчет со списком оформленных кредитов, поручителями по которым выступали шестилетние дети. Естественно, у пользователей такого отчета возник вопрос, когда это организация начала выдавать кредиты детям! Конечно же, это не так. Просто где-то на уровне ниже закралась логическая ошибка. И подобные случаи составляют основной костяк данной части работы.
Итак, переходим к основному рассмотрению поэтапного решения подобного вида проблем.
Конечно же, первое что нужно знать, или уметь, или применять, это различные методы профилирования, актуальность применения которых зависит от конкретной задачи.
1. Проверка актуальности проблемы
Как правило, к вам со стороны бизнеса приходят и говорят, что такая-то таблица возвращает не то что надо, и чаще всего прикладывается скрипт, написанный на SQL или Python, запустив который, можно вернуть некорректные данные.
А значит, шаг первый – запустить его на предмет актуальности проблемы. Возможно, проблема уже устранена. Очень часто коллеги заводят сразу несколько одинаковых заявок на одну проблему.
Шаг второй же – проверить, основываясь на вашем внутрипроектном опыте и понимании той предметной области, с которой вы на данный момент работаете, корректность предоставленного вам проверочного скрипта.
Важное дополнение. Думайте, что запускаете. Не в каждой компании настроена защита информационной безопасности. Проще говоря, если сомневаетесь, стоит ли исполнять проверочный скрипт, где присутствует, к примеру, DROP TABLE, лучше провести дополнительную проверку. Как вариант, это может быть создание временных таблиц, скопированных с оригинала, и запуск на них проверочного скрипта.
2. Свериться с документацией
Здесь требуется учитывать все аспекты специфики вашего Data Contract на том проекте, на котором вы сейчас работаете.
Оговоримся, варианты анализа могут быть разными, все зависит от вашего текущего проекта.
Здесь все просто. Год назад вы сделали задачу и вывели данные по кредиту, а именно его номер, сумму и срок. И сделали это в соответствии с разработанным и согласованным планом, сметой на работы, написали документацию, описали в ней, что выводится и как это будет выглядеть. Затем прошло время, и бизнесу потребовалось выводить в отчет еще, например, и валюту. Но, если ваш поток данных работает согласно действующей документации корректно, то данный запрос бизнеса – это уже полноценная доработка, а не проблема. В таком случае следует возвратиться к заявителю проблемы с соответствующей обратной связью.
Как пример, можно следовать следующим этапам:
№ | Проверки |
1 | Сверка с регламентами |
2 | Сверка с артефактами |
3 | Сверка с действующей логической моделью анализируемых данных |
3. Свериться с источником данных
Здесь имеется ввиду проверка корректности поставляемых данных с самого источника. Если данную проверку не сделать, есть риск скорректировать код, который исправит только эту ошибку, но сгенерирует кучу ранее не наблюдаемых.
Возьмем в пример ранее описанный кейс с малолетними (6-9 лет) поручителями по кредитам. Прежде чем погружаться в код, есть смысл посмотреть сразу на источник, возможно уже на нем присутствуют подобные поручители. В таком случае вы никак не сможете повлиять на корректность данных в отчете.
В описанных этапах ниже данный пример будет приведен лишь как теоретический, так как здесь как раз вопрос был в источнике, то есть таких клиентов нам в технический отдел поставляли сами операционисты. Что в итоге и уточнили, собрав предварительно весь материал во вложение в письме, у руководителя, отвечающего за операционную работу.
В таких случаях следует просто написать на заявителя соответствующую обратную связь и переводить проблему на тот отдел, в котором она появилась.
Но вернемся к нашим этапам.
Говоря о сверке с источником, рекомендуется собрать статистику по аналогичным ошибкам, и если таких будет много, сразу оповестить об этом сотрудников источника, чтобы они своевременно их устранили.
Вместе с этим следует учесть, что источников, которые собирают требуемые витрины, может быть много. Обязательно следует это проверить и учесть в дальнейшей работе над задачами.
4. Локализация причины возникновения проблемы
Если проблема все еще актуальна, к документации не придраться и источник кладет корректные данные, переходим к анализу потока данных.
В любой компании каждый поток данных использует свои брокеры сообщений, свой код, свою логику. Где-то работа более стандартизирована, где-то менее. Но именно в такого рода потоках всегда используется поэтапное изменение как самих данных в таблицах, так и структуры самих таблиц, до требуемого заказчиками вида. В самой упрощенной форме, источник данных – это первая таблица, приемник – какая-то n-ая, допустим десятая. И вот где-то между первой и десятой у нас закралось то преобразование, которое стало причиной прокладки некорректных данных на конечный приемник. Отследить причину довольно просто. Достаточно поэтапно двигаться от последней таблицы к первой до тех пор, пока не дойдете до той таблицы, где с данными все в порядке.
Пример.
Допустим у нас есть таблица 1, это источник,
Таблица 1 | |
id Поручителя | Возраст поручителя, лет |
1 | 20 |
и таблица 10, приемник. Вы знаете, что данные в таблице 1 корректные (поручителю 20 лет), а в таблице 10 – нет (поручителю 2 года).
Таблица 10 | |
id Поручителя | Возраст поручителя, лет |
1 | 2 |
Тогда просто шагаете по таблицам вверх. Допустим вы прошагали таблицы 10, 9, 8, 7 и там возраст поручителя (2 года) не менялся, а в таблице 6 изменился и стал 20 лет:

Это значит, что в таблице 7 было сделано какое-либо преобразование, которое сменило возраст. Поздравляю, горлышко бутылки найдено.
Конечно же, был описан общий план действий, могут и будут возникать нюансы. Но если придерживаться данного плана, вы точно найдете причину проблемы.
5. Устранение проблемы
Для конкретизации рассмотрим выше описанную инструкцию на трех примерах.
Все примеры с проблематикой и устранением записаны именно в этом блоке, так как первые 4 блока были общей подготовительной частью для любых кейсов, связанных с запросами на корректировку данных в конечных витринах.
Итак, причина найдена. Проблема в коде. Теперь надо его исправить.
Пример первый
Ошибка в сущности связи между кредитной сделкой и контрагентом: на одну сделку приходится два контрагента с разными типами, но бизнес ключ у них один и обе записи действующие, пришедшие в один день. Соответственно, непонятно, какая запись по итогу актуальная.
сущность связи сделки с контрагентом | ||||
id_сделки | тип_контрагента | id_контрагента_бизнес | дата_начала_записи | дата_окончания_записи |
1 | бывший заемщик | 444 | 20.12.2025 | 31.12.2999 |
1 | заемщик | 444 | 20.12.2025 | 31.12.2999 |
По смыслу, это дубль записи.
Устранение проблемы
Здесь выяснилось, что не было учтено условие, когда клиент может поменять роль в один день. В данном случае заемщик стал бывшим заемщиком по причине ухода из жизни. Но на источнике записи со временем были. В данном случае просто добавили условие на максимальную дату изменения записи по контрагенту, а более старую запись отсекли. Такие действия позволили нам сделать требования к модели, поэтому решили так. Сделали через оконную функцию:
Select *, Row_number() over(partition by id_сделки, id_контрагента_бизнес, дата_начала_записи(с источника со временем) order by дата_начала_записи(с источника со временем desc) rn,
Затем сделали фильтр на отсечение записей, где rn !=1.
Пример второй
Ошибка в сущности связи сделки вклада и счета, на котором хранились денежные средства: не отображались данные предыдущего счета в случае пролонгации вклада.
Как было:
сущность связи вклада со счетом | ||||
id_вклада | id_счета_суррогат | тип_счета | дата_начала_записи | дата_окончания_записи |
1 | 333 | счет для основной суммы | 22.12.2025 | 31.12.2999 |
Как должно было быть:
сущность связи вклада со счетом | ||||
id_вклада | id_счета_суррогат | тип_счета | дата_начала_записи | дата_окончания_записи |
1 | 222 | счет для основной суммы | 20.12.2025 | 22.12.2025 |
1 | 333 | счет для основной суммы | 22.12.2025 | 31.12.2999 |
Устранение проблемы
Здесь в принципе не была построена историчность. Было условие на отсечку всех записей кроме последней актуальной. Выстраивали с помощью оконной функции lead, включая отсеченные записи источника:
Select *, Lead(дата_начала_записи) over(partition by id_вклада, тип_счета order by дата_начала_записи) as дата_окончания_записи
Пример третий
В сущности сделки по депозиту не было даты пролонгации депозита.
Как было:
сущность депозитная сделка | |||||
id_депозита | id_счета_суррогат | тип_счета | дата_пролонгации | дата_начала_записи | дата_окончания_записи |
1 | 222 | счет для основной суммы | NULL | 20.12.2025 | 31.12.2999 |
Как должно было быть:
сущность депозитная сделка | |||||
id_депозита | id_счета_суррогат | тип_счета | дата_пролонгации | дата_начала_записи | дата_окончания_записи |
1 | 222 | счет для основной суммы | 19.08.2025 | 20.12.2025 | 31.12.2999 |
Устранение проблемы
Это оказалось самым простым. Код клал все корректно, просто на момент загрузки первой сделки источник действительно не передавал данные о пролонгации, мы просто перезапустили поток с начала времен, и данные легли как надо.
Общий итог
Подводя итог выше описанному, при работе с проблемами качества данных в витринах, можно опираться на следующую таблицу пошаговой инструкции:
№ | Наименование | Описание |
1 | Проверка актуальности проблемы | Возможно ее уже и нет |
2 | Сверка с текущей документацией | Работает ли ваш поток согласно описанной ЛМД, концептам, маппингам, артефактам |
3 | Сверка с источником данных | Проверка на корректность данных, приходящих из источника |
4 | Локализация причины возникновения проблемы | Пошаговый селект временных таблиц от конца к началу или наоборот |
5 | Устранение проблемы | Корректировка кода в соответствии с требованиями по задаче |
Повторимся, пункты описаны исходя из практики по устранению ошибок в потоке, и их соблюдение не раз спасало меня от лишней траты огромного количества сил, нервов и времени.
Удачи вам в вашей работе!
