В предыдущей статье мы поговорили про роль Data Engineer в Х5, какие задачи он решает и с каким технологическим стеком работает. Рассмотрели структуру собеседования, основные направления, по которым мы оцениваем кандидатов, и подробно разобрали базовые требования, предъявляемые нами к уровню владения Python. В данной статье мы разберём требования к ключевым для Data Engineer в X5 навыкам: распределённые системы и вычисления на Hadoop / Spark, а также SQL и проектирование схемы данных. Важно отметить, что здесь наши ожидания не ограничиваются базовыми знаниями и умением решать типовые задачи. Мы хотим видеть более глубокий уровень понимания и владения данными технологиями, способность решать сложные или нестандартные задачи. В продуктовых  командах работать с Hadoop, Spark и реляционными базами данных на базовом уровне умеют многие: Data Scientists, Data Analysts и Data Quality. Для этого прикладываем много усилий по обучению сотрудников: отправляем на обучение к внешним провайдерам, приглашаем внешних экспертов с лекциями, организуем мастер-классы, разрабатываем и преподаем специальные программы в рамках внутренней цифровой академии. Таким образом, Data Engineer в Х5 — не тот человек, в которого сыплются все задачи, когда нужны данные, а тот, кого зовут для решения более сложных и нетривиальных технических задач, где базовых знаний соответствующих технологий уже не достаточно. По этим причинам мы на интервью смотрим, насколько глубоко кандидат разбирается в том, что происходит под капотом той или иной технологии. Без этих знаний он навряд ли сможет успешно справиться с нашими задачами. Мы стараемся строить обсуждение вокруг открытых вопросов, и в ходе этой беседы спрашиваем по более узким темам. И если такое обсуждение с каждым шагом начинает затрагивать все более и более сложные темы, то это означает лишь одно: вы прекрасно справляетесь и каждое новое усложнение даёт вам дополнительные очки. Приведу несколько примеров таких вопросов. Ваш коллега, начинающий Data Analyst, собирается построить новую витрину и попросил вас посмотреть код его скрипта на Spark. В коде есть фрагмент, где предполагается провести партиционирование по полю типа double с диапазоном возможных значений от нуля до миллиарда. Что вы на это скажете? Здесь мы хотим услышать не краткий ответ вида «Так делать нельзя» или «Норм, давай запустим», а более развёрнутый ответ, в котором можно проследить следующие рассуждения: Партиционирование по этому полю приведет к созданию потенциально огромного числа маленьких файлов в HDFS. Наличие сотен миллионов маленьких файлов может привести к проблемам всего Hadoop кластера. Проблема с кластером Hadoop может возникнуть из-за отказа NameNode. Отказ NameNode может произойти потому, что мета-информация о файловой системе хранится в оперативной памяти NameNode, и её объёма может просто не хватить. Если далее вам предложили развить тему, например, в направлении того, как можно обеспечить высокую доступность NameNode и избавиться от единой точки отказа, то это означает, что вы отлично справляетесь, и есть смысл затронуть более сложные темы. К вам снова обратился за помощью ваш коллега, начинающий Data Analyst. В этот раз у него проблема с тем, что разработанный им алгоритм прекрасно работает на семплированных данных из большого датасета, но на всём огромном датасете возникает множество проблем. Какие возможные типовые проблемы вам приходят в голову? Это очень общий вопрос, в ходе обсуждения которого мы бы хотели, чтобы кандидат, среди прочего, затронул тему дисбаланса в данных и то, как с ним справиться. Тема дисбаланса даёт отличный контекст для разговора про поиск узких мест, оптимизацию вычислений, про разные виды join в Spark, чем они отличаются, когда применяются и тому подобное. Совет: вспомните и расскажите про самые сложные, на ваш взгляд, проблемы и ошибки, с которыми вы сталкивались, как их решили и чему научились. Если про проблему маленьких файлов в hadoop вы знаете не в теории, а потому что в своё время завалили кластер, а потом досконально разобрались в том, почему так делать не стоит, — это даст вам дополнительные очки в наших глазах.  Вам нужно посчитать количество уникальных значений в неком числовом поле, которое имеет тип Long (8 байт). Какой запрос вы для этого напишете? Расскажите, как Spark будет выполнять этот запрос, настолько детализировано, насколько сможете. Данный вопрос, при всей своей кажущейся простоте, имеет несколько вложенных уровней сложности и позволяет достаточно точно определить позицию кандидата по шкале от «может написать запрос» до «имеет знания редкой глубины». Ещё раз напомню, что каждый новый виток усложнений, когда вас просят детальнее рассказать про те или иные аспекты, означает, что вы на верном пути, и пока всё идёт хорошо. Совет: вспомните кейсы из вашей практики, когда вам приходилось оптимизировать вычисления и вникать в то, как именно исполняет запросы Spark. Мы спросим вас про такие кейсы, и тогда разговор можно будет построить вокруг них, что будет для вас гораздо комфортнее, чем общие вопросы. Обычно мы просим кандидата спроектировать небольшую схему и написать SQL-запрос для решения определённой задачи. Цель специально ставится в очень общей формулировке, и ожидается, что кандидат прежде всего начнет с уточнения требований и ограничений, прежде чем предлагать решение или писать какой-либо код. Вас просят спроектировать схему данных и написать запросы для формирования дашборда по РТО (розничный товарооборот) и маржинальности магазинов новой торговой сети «Десяточка» по месяцам в разрезе городов и категорий товаров. Здесь мы ожидаем, что кандидат сначала будет уточнять постановку задачи, например, так:  Сколько товаров, магазинов и категорий? — 100К товаров, 20К магазинов, 300 категорий. Сколько продаж в месяц?  — Пара миллиардов записей каждый месяц. За какой период храним данные? — За несколько лет, накапливаем новые данные по продажам. Как часто обновляются данные? — Раз в месяц. Какого рода запросы предполагается обрабатывать? — Сценарии использования могут быть разными: к примеру, посмотреть, как изменялись помесячно товарооборот и маржинальность по определенным категориям за последние три года или посмотреть топ-10 городов по товарообороту для всех категорий за последний месяц. Совет: если вы затрудняетесь предложить решение, которое удовлетворяет всем заданным условиям, выберите ту часть требований, для которых вы можете предложить решение и сосредоточьтесь на них. Явно обозначьте, каким ограничениям ваш вариант удовлетворяет, а каким нет — это совершенно нормальный вариант развития событий. Одно из возможных решений, которое можно предложить, опираясь на полученные вводные, приводим ниже. Продаж в месяц очень много (более двух миллиардов), хочется хранить и накапливать их историю. Для этих целей хорошо подойдет БД Hive, но она не справится с быстрой аналитикой данных для дашборда, поэтому можем реализовать решение в два этапа: Храним сырую историю продаж в Hive. Сырые продажи можно агрегировать в нужном нам виде (месяц, город, категория) и загружать в более быструю базу для аналитики (OLAP). В качестве такой базы можно использовать ClickHouse, он способен быстро давать результат по аналитическим запросам.  Подход к решению предложен, теперь набросаем возможную структуру схемы для хранения данных. Начнём с Hive. Теперь перейдём к ClickHouse. Запрос для первичной загрузки данных в Clickhouse. Запрос для загрузки новых данных за очередной месяц. Пример запроса для дашборда: сумма всех категорий по городам за текущий месяц. Пример запроса для дашборда: сумма всех городов по категориям за текущий месяц. Если у вас есть опыт с Docker, K8S, Airflow, NoSQL, Kafka или Gitlab Ci/CD, то нам было бы интересно его обсудить. Типовых вопросов тут как правило нет, мы отталкиваемся от того, что про свой опыт рассказывает кандидат и точечно проясняем интересующие нас моменты. Надеемся, что эта информация позволит вам составить верное представление о том, как проходит интервью, чего стоит ожидать и как лучше подготовиться. Мы ищем Data Engeneer со знанием Python, Hadoop, Spark. Чтобы узнать подробности, можно посмотреть нашу вакансию.