Перейти к основному содержимому

Сильнее вместе: Python, датафреймы и SQL

· 12 мин. чтения
Doug Beatty

Много лет, работая в области данных и аналитической инженерии, я ценил ежедневное общение в небольшом офисе с талантливыми людьми, использующими различные инструменты — от аналитиков, работающих с SQL и Excel, до дата-сайентистов, работающих с Python. Я всегда чувствовал, что у нас есть много возможностей для совместной работы, но изолированные данные и инструменты делали это гораздо сложнее. Разнообразие наших инструментов и языков делало потенциал для сотрудничества еще более интересным, поскольку у нас могли быть люди с разными областями экспертизы, каждый из которых вносил бы свой уникальный вклад в проект. Но с логистической точки зрения это просто не могло быть реализовано в масштабируемом виде.

Поэтому я не могу быть более взволнован возможностями полиглотности dbt, которые появились в dbt Core 1.3. Этот релиз приносит библиотеки датафреймов Python, которые важны для дата-сайентистов, и позволяет использовать Python общего назначения, но при этом использует общую базу данных для чтения и записи наборов данных. Аналитические инженеры и дата-сайентисты сильнее вместе, и я не могу дождаться, чтобы работать бок о бок в одном репозитории со всеми моими друзьями-дата-сайентистами.

Переход на полиглотность — это важный следующий шаг в развитии dbt Core. Хотя это расширяет возможности, мы также признаем потенциал для путаницы. Когда они объединены намеренно, SQL, датафреймы и Python также сильнее вместе. Полиглотный dbt позволяет информированным практикам выбирать язык, который лучше всего подходит для вашего случая использования.

В этом посте мы дадим вам практический опыт и вдохновим ваше воображение потенциальными приложениями. Мы проведем вас через демонстрацию, которая демонстрирует разбор строк — один из простых способов, как Python может быть интегрирован в проект dbt.

Мы также предоставим вам интеллектуальные ресурсы для сравнения:

  • различных реализаций датафреймов в разных платформах данных
  • датафреймы против SQL

Наконец, мы поделимся "подводными камнями" и лучшими практиками, которые мы узнали до сих пор, и пригласим вас участвовать в поиске ответов на нерешенные вопросы, которые нас самих все еще интересуют.

На основе нашего раннего опыта, мы рекомендуем вам:

Делайте: Используйте Python, когда он лучше подходит для задачи — обучение моделей, использование предсказательных моделей, матричные операции, исследовательский анализ данных (EDA), пакеты Python, которые могут помочь с комплексными трансформациями, и другие случаи, когда Python является более естественным решением для проблемы, которую вы пытаетесь решить.

Не делайте: Используйте Python там, где решение на SQL столь же прямолинейно. Хотя чисто Python проект dbt возможен, мы ожидаем, что наиболее значимые проекты будут смесью SQL и Python.

Полиглотный dbt: Сплав Python, датафреймов и SQL

dbt Core 1.3 дает вам возможность использовать модели Python для материализации датафреймов как таблиц в вашем dbt DAG. В комбинации, модели Python и SQL формируют сплав в проекте dbt, создавая новые свойства, которых нет в изоляции.

Это одновременное двухчастное разблокирование. Во-первых, мы получаем язык программирования общего назначения в Python. Во-вторых, мы получаем доступ к специализированным библиотекам датафреймов для чтения из/записи в базу данных.

Некоторые довольно крутые функции следуют:

  1. Обширная экосистема пакетов Python: Богатая экосистема пакетов Python является сердцем различных случаев использования, таких как машинное обучение, исследовательский анализ данных (EDA), генерация наборов данных и многие, многие другие.
  2. Синтаксис датафреймов для манипуляции наборами данных: Существует активное сообщество разработчиков, ориентированных на Python, которые могут легче вносить вклад в проекты dbt, когда они могут использовать синтаксис датафреймов. Это особенно полезно в сочетании с случаями использования в области науки о данных.
  3. Рабочие процессы Python там, где находятся ваши данные: Большая часть работы с Python сегодня выполняется вне платформы данных, которая хранит исходные данные, что означает, что разработчикам сначала нужно перенести данные в среду Python, что добавляет значительное трение в рабочий процесс разработки. В случае Snowpark DataFrames перемещение данных сокращается за счет переноса вычислений на платформу данных.

Компромиссы между SQL и синтаксисом датафреймов

Как только вы настроитесь, следующий вопрос: для чего следует использовать Python? Как следует думать о компромиссах между SQL и датафреймами? Я лично не задумывался об этом глубоко... но ребята из Ponder задумывались 😉 Они опубликовали серию постов, сравнивающих их с точки зрения:

  • удобства - датафреймы хорошо сочетаются с библиотеками науки о данных, такими как Scikit-learn
  • краткости - датафреймы имеют краткий синтаксис для нормализации, one-hot кодирования, скользящих средних и других применений
  • гибкости - строки и столбцы в датафреймах могут быть транспонированы, и функции могут быть применены вдоль столбцов или строк

Получение вашего собственного понимания этих различий позволит вам создать свой собственный сплав полиглотных моделей dbt.

Сравнение библиотек датафреймов

Прежде чем мы перейдем к нашему практическому примеру, давайте взглянем на детали настройки вашего проекта с различными типами датафреймов. Несколько платформ данных и библиотек датафреймов поддерживаются в dbt Core начиная с версии 1.3, но не равномерно (см. таблицу совместимости ниже). См. здесь для инструкций по настройке для конкретной платформы.

Тип датафреймаSnowflakeDatabricksBigQuery
Snowpark DataFrames
pandas DataFrames
Spark DataFrames
pandas-on-Spark DataFrames
Koalas DataFrames
Более детальные сравнения и компромиссы

Snowpark DataFrames поддерживаются только в Snowflake, в то время как Spark DataFrames доступны только на Databricks и BigQuery. Также стоит помнить, что разные типы датафреймов используют разный синтаксис.

Мы намеренно не включили Jinja в модели Python: основное использование Jinja заключается в управлении потоком и доступе к динамическим переменным, что можно сделать в Python! Другое основное использование Jinja в dbt — создание абстракций для различных синтаксисов баз данных. На данный момент нет единой абстракции синтаксиса для различных типов датафреймов. (Но кто-то, вероятно, создаст одну!)

Хотя pandas DataFrames могут показаться идеальным решением из-за их поддержки на различных платформах данных, они имеют свои собственные компромиссы. Например, они не могут воспользоваться эффективностью нативных типов, таких как Spark и Snowpark DataFrames. Они также ограничены памятью — большие наборы данных быстро исчерпают доступную память. В дополнение к этому, они ограничены однопоточностью, поэтому не могут использовать несколько ядер. Хотя pandas можно параллелизовать с помощью решений, таких как Dask, Modin и т.д., как Snowpark, так и Spark DataFrames будут обрабатывать эти проблемы масштабирования нативно. Поэтому используйте Snowpark, pandas-on-Spark DataFrames и Spark DataFrames, когда это возможно! (Примечание: pandas-on-Spark DataFrames ранее были известны как Koalas DataFrames и теперь обычно называются pandas API DataFrames.)

В Snowflake любые трансформации Snowpark DataFrame, указанные в Python, фактически компилируются в SQL перед выполнением.

Первый практический опыт использования пакета Python

Теперь, когда у нас есть достаточный фон, давайте погрузимся в реальный случай использования.

Полный исходный код для этой демонстрации доступен по адресу:

Этот пример использует DuckDB в качестве базы данных. Вы можете использовать этот же код, скопировав его в свой проект, который использует ваш адаптер базы данных.

Наш пример даст вам практический опыт с тремя вещами:

  1. чтение данных из таблицы в датафрейм
  2. разбор унифицированных дат и времени из различных строковых форматов с использованием библиотеки dateutil
  3. запись результата обратно в таблицу

Разбор дат/времени — это распространенный случай использования, потому что даты и время повсеместны в транзакционных исходных данных. Часто исходный формат неизвестен, и он может даже быть смесью нескольких форматов. Пакет dateutil имеет метод, который будет делать попытку разбора строки в объект даты и времени Python, и он вызовет исключение, когда не сможет разобрать ввод. (Пользователи pandas могут уже быть знакомы с методом pandas.to_datetime, который использует dateutil). Следующая демонстрация использует dateutil для разбора исходных данных с неизвестными форматами даты/времени.

В этом примере мы:

  1. Установим требования в виртуальной среде
  2. Построим проект dbt
  3. Проверим вывод

Компоненты проекта dbt

Этот проект dbt имеет только две основные части (помимо наших исходных данных для имитации исходных данных):

  1. Логика трансформации в модели dbt Python
  2. Конфигурация тестирования данных для обеспечения качества

Модель dbt на Python

import dateutil


def try_dateutil_parse(x):
try:
return dateutil.parser.parse(x)
except:
return


def model(dbt, session):
df = dbt.ref("source_data")

df['parsed_transaction_time'] = df['transaction_time'].apply(try_dateutil_parse)

return df

Эта модель пытается разобрать необработанное строковое значение в объект даты и времени Python. Когда это не удается, она возвращает значение None, а не вызывает ошибку. dateutil может обрабатывать более широкий диапазон форматов, чем большинство нативных функций платформ данных.

Тестирование результата

Во время процесса сборки dbt проверит, есть ли какие-либо значения null. Это использует встроенный тест not_null, который будет генерировать и выполнять SQL на платформе данных.

Наше первоначальное предложение для тестирования моделей Python — использовать общие и единичные тесты.

version: 2

models:
- name: transactions
columns:
- name: parsed_transaction_time
tests:
- not_null

Загрузка репозитория и установка требований

Полный исходный код для этой демонстрации доступен по адресу:

Единственные предварительные условия для этой демонстрации — это python3 и git. Вы можете убедиться, что оба установлены и вы используете правильную версию, с помощью этих команд в вашем терминале:

python3 --version
git --version

Предполагая, что оба доступны в вашей системе, вы можете клонировать пример репозитория, используя ваш предпочтительный метод:

HTTPS
git clone https://github.com/dbt-labs/demo-python-blog.git
cd demo-python-blog
SSH
git clone git@github.com:dbt-labs/demo-python-blog.git
cd demo-python-blog
GitHub CLI
gh repo clone dbt-labs/demo-python-blog
cd demo-python-blog

Затем вы создадите виртуальную среду и установите все зависимости. Выберите вашу оболочку / операционную систему из списка ниже и выполните команды (по умолчанию zsh/bash):

POSIX bash/zsh
python3 -m venv env
source env/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
source env/bin/activate
POSIX fish
python3 -m venv env
source env/bin/activate.fish
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
source env/bin/activate.fish
POSIX csh/tcsh
python3 -m venv env
source env/bin/activate.csh
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
source env/bin/activate.csh
POSIX PowerShell Core
python3 -m venv env
env/bin/Activate.ps1
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
env/bin/Activate.ps1
Windows cmd.exe
python -m venv env
env\Scripts\activate.bat
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
env\Scripts\activate.bat
Windows PowerShell
python -m venv env
env\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
env\Scripts\Activate.ps1

Построение

Как только все зависимости установлены, мы можем построить проект:

dbt build

Запрос результата трансформации dbt

Поздравляем с успешным запуском вашей первой модели dbt на Python! Давайте подтвердим вывод визуально, выполнив следующий запрос:

duckcli demo.duckdb --table --execute "select id, transaction_time, parsed_transaction_time from parse_datetimes order by id"

Как вы можете видеть, каждый из различных входных форматов был успешно разобран в унифицированный и стандартизированный формат.

idtransaction_timeparsed_transaction_time
1Fri, 16 Dec 2022 02:59:36 +00002022-12-16 02:59:36
2Sun, 25 Dec 22 02:59:36 +00002022-12-25 02:59:36
3Thursday, 31-Mar-22 02:59:36 UTC2022-03-31 02:59:36
4Thu, 02 Jun 22 02:59:36 +00002022-06-02 02:59:36
5Thu, 17 Feb 2022 02:59:36 +00002022-02-17 02:59:36
62022-03-28 02:59:36+00:002022-03-28 02:59:36
72022-10-22 02:59:36+00:002022-10-22 02:59:36
82022-10-02 02:59:36+00:002022-10-02 02:59:36
9Monday, 03-Jan-2022 02:59:36 UTC2022-01-03 02:59:36
10Thu, 25 Aug 2022 02:59:36 +00002022-08-25 02:59:36
112022-05-29T02:59:36+00:002022-05-29 02:59:36
122022-08-02 02:59:36+00:002022-08-02 02:59:36
132022-10-18 02:59:36+00:002022-10-18 02:59:36

⚠️ Не забудьте деактивировать среду как последний шаг:

deactivate

И вот так! Реальный пример использования Python для распространенного аналитического случая! Теперь давайте подумаем о том, что мы узнали.

Рекомендации по лучшим практикам

На основе нашего раннего опыта использования моделей dbt на Python и наших текущих разговоров с членами сообщества dbt, вот некоторые рекомендованные "делайте и не делайте", которые, как мы думаем, помогут вам добиться успеха.

Делайте:

  • Используйте Python, когда он лучше подходит для задачи — обучение моделей, использование предсказательных моделей, матричные операции, исследовательский анализ данных (EDA) и пакеты Python, которые могут помочь с комплексными трансформациями.
  • Используйте нативный тип датафрейма и синтаксис для вашей платформы данных. Используйте среду ноутбука (и небольшой образец вашего набора данных) для начальной разработки перед копированием его в dbt.

Не делайте:

  • Используйте Python там, где решение на SQL столь же прямолинейно. Хотя чисто Python проект dbt возможен, мы ожидаем, что наиболее значимые проекты будут смесью SQL и Python.
  • Выполняйте веб-скрапинг или загружайте данные из интернета.
  • Используйте pandas, если это не абсолютно необходимо. Хотя pandas может быть полезен на этапе прототипирования, масштабирование до больших наборов данных часто требует платформенного нативного типа, такого как Snowpark, Spark или pandas-on-Spark.
  • Переводите весь ваш проект на Python. Хотя это возможно, если модели уже написаны на SQL и нет конкретной выгоды от их перевода на Python, просто оставьте их как SQL.

🤷 Мы еще не знаем!

Есть несколько нерешенных вопросов, в обсуждение которых вы приглашены внести свой вклад:

Заключение

Python особенно хорошо подходит для многих случаев использования в проекте dbt, включая:

  • Наука о данных: обучение моделей или развертывание в реальном времени
  • Использование пакетов в экосистеме Python, таких как ftfy, dateutil и т.д.
  • Исследовательский анализ данных (EDA) с использованием функций и пакетов, таких как pandas.describe, Pandas profiling, Great Expectations и т.д.
  • Генерация синтетических наборов данных с использованием Faker
  • Линейное программирование с использованием библиотек, таких как CVXOPT, PULP, CVXPY, ECOS, Google OR-Tools, SciPy и т.д.
  • Моделирование с использованием SimPy, Монте-Карло моделирование, анализ "что если"
  • И многое другое!

Нет одного языка программирования, который бы правил всеми, поэтому нет языка программирования, за который мы будем бороться до конца! Мы обеспечим, чтобы dbt поддерживал широкий спектр языков и позволял вам принимать обоснованные решения для каждого отдельного случая использования.

Мы с нетерпением ждем, что вы откроете и создадите! Пожалуйста, поделитесь с нами в каналах #dbt-core-python-models или #i-made-this в Slack.

Comments

Loading