Чего не хватает в PL/Python и зачем нужна еще одна библиотека для создания Python-скриптов обработки данных в Greenplum. Возможности API GreenplumPython и сравнение с pandas.
Что такое PL/Python и как это работает в Greenplum
Мы уже писали, что Greenplum изначально поддерживает Python, предоставляя PL/Python – загружаемый процедурный язык, который позволяет писать пользовательские функции и процедуры на этом популярном языке программирования. Разработчик может запускать блоки кода PL/Python как анонимные блоки кода. Для этого вместе с базой данных по умолчанию устанавливаются 2 расширения PL/Python:
- plpythonu, которое поддерживает разработку функций с использованием Python7;
- plpython3u для разработки функций с использованием Python9, впервые представленное в Greenplum версии 6.22.
Пере тем как создать и запустить пользовательскую функцию PL/Python в базе данных, следует зарегистрировать этот язык с помощью команды SQL CREATE EXTENSION, что может сделать только пользователь категории superuser. Это надо сделать на всех хостах каждого сегмента кластера. Для анализа данных в этих расширениях поддерживаются Python-модули Data Science, предоставляемые в виде двух файлов формата .gppkg, которые надо установить в кластер Greenplum с помощью утилиты gppkg. Для работы с другими модулями можно использовать утилиты gpssh и gpsync, для выполнения команд или копирования файлов на все хосты в кластере Greenplum.
В PL/Python тело UDF-функции представляет собой Python-скрипт. При вызове функции ее аргументы передаются как элементы массива args[], а именованные аргументы передаются как обычные переменные. Результат возвращается функцией PL/Python с оператором return или оператором yield. Без указания возвращаемого значения, Python вернет значение по умолчанию None, которое PL/Python переводит в NULL-значение SQL. Если возвращаемый результат UDF-функции является логическим, Greenplum оценивает его на предмет истинности в соответствии с правилами Python: 0 и пустая строка являются ложными, но f считается истинным результатом (true), что может слегка запутать начинающего дата-инженера.
В PL/Python модуль plpy предоставляет две Python-функции для запуска SQL-запроса и подготовки плана его выполнения: plpy.execute и plpy.prepare. Подготовка плана выполнения SQL-запроса полезна, когда он запускается из нескольких Python-функций. PL/Python также поддерживает функцию plpy.subtransaction(), чтобы управлять вызовами plpy.execute в явной подтранзакции.
Вызов plpy.execute со строкой запроса и необязательным аргументом limit приводит к выполнению запроса и возврату результата в Python-объекте, который эмулирует объект списка или словаря. Доступ к строкам, возвращенным в объекте результата, можно получить по номеру строки и имени столбца. Нумерация строк набора результатов начинается с 0. Объект результата имеет следующие дополнительные методы: nrows — количество строк, возвращенных запросом и статус, который является возвращаемым значением SPI_execute().
Функция plpy.prepare подготавливает план выполнения запроса. Он вызывается со строкой запроса и списком типов параметров, если в запросе есть ссылки на параметры. При подготовке плана выполнения с помощью PL/Python, он автоматически сохраняется. Чтобы эффективно использовать сохраненные планы при вызовах функций, следует использовать один из словарей постоянного хранилища Python SD или GD.
Глобальный словарь SD доступен для хранения данных между вызовами функций. Эта переменная является закрытыми статическими данными. Глобальный словарь GD является общедоступными данными, доступными для всех функций Python в рамках сеанса. Использовать глобальный словарь GD надо с большой осторожностью, поскольку каждая функция получает свою собственную среду выполнения в интерпретаторе Python. Например, глобальные данные и аргументы функции из myfunc() будут недоступны для myfunc2().
Для управления ошибками PL/Python-модуль plpy реализует целый ряд функций (plpy.debug, plpy.log, plpy.info, plpy.notice, plpy.warning, plpy.error, plpy.fatal, plpy.debug). Например, функции сообщений plpy.error и plpy.fatal (а также эквивалентные им plpy.ERROR(msg) и plpy.FATAL(msg)) вызывают исключение Python, которое, если его не перехватить, распространяется на вызывающий запрос, вызывая отмену текущей транзакции или подтранзакции. Другие функции сообщений генерируют только сообщения с разными уровнями приоритета, которые передаются клиенту или записываются в журнал сервера, в зависимости от параметров его конфигурации log_min_messages и client_min_messages.
С точки зрения производительности импорт Python-модуля является дорогостоящей операцией и может снизить производительность СУБД. Вместо этого можно использовать глобальные переменные Python для загрузки модуля при первом вызове, чтобы избежать его импорта при последующих.
Поскольку процедура, в отличие от функции, обычно не возвращает значение определенного типа, то в процедуре PL/Python результатом Python-кода является None. Это достигается завершением процедуры без оператора return или использованием оператора return без аргумента. Иначе будет вызвана ошибка. В процедуре или анонимном блоке кода (команда DO), вызываемых с верхнего уровня, можно управлять транзакциями. Для фиксации текущей транзакции используется метод plpy.commit(), а для ее отката — plpy.rollback(). Примечательно, что команды SQL COMMIT или ROLLBACK невозможно запустить с помощью plpy.execute(). После завершения транзакции новая транзакция запускается автоматически, поэтому отдельной функции для нее не требуется.
В заключение стоит сказать про ограничения PL/Python в Greenplum:
- не поддерживаются триггеры, о которых мы рассказываем здесь;
- не поддерживаются обновляемые курсоры в выражениях UPDATE…WHERE CURRENT OF и DELETE…WHERE CURRENT OF;
- все функции PL/Python в рамках одного сеанса Greenplum должны вызываться с использованием расширения plpythonu или plpython3u. Придется каждый раз начать новую сессию, чтобы вызвать функцию, созданную с другой версией PL/Python, например, чтобы вызвать функцию plpythonu после вызова plpython3u или наоборот.
Подводя итог краткому рассмотрению PL/Python, можно сделать вывод, что это достаточно мощное средство разработки, несмотря на некоторые ограничения. Однако, оно скорее предназначено для профессиональных разработчиков, а аналитики данных и Data Scientist’ы привыкли к более легковесным решениям. Именно для этой категории пользователей предназначена Python-библиотека GreenplumPython, с которой мы познакомимся далее.
Обзор библиотеки GreenplumPython
Python-библиотека GreenplumPython масштабирует работу с данными путем создания API, который позволяет пользователям обрабатывать и манипулировать таблицами из миллиардов строк в Greenplum, используя легковесные Python-конструкции, без экспорта данных на свои локальные машины. В частности, аналитик данных и Data Scientist может писать Python-код привычным для себя образом, используя функции пакета pandas, чтобы выполнять преобразования данных и обучать ML-модели на платформе Greenplum без глубоких знаний SQL. GreenplumPython сама отправляет все свои операции в хранилище данных Greenplum как SQL-операторов.
Для работы GreenplumPython требуется как минимум Python 3.9, которая официально поддерживается вместе с PL/Python3 и GPDB 6, а также является версией по умолчанию в Rocky Linux 9 и RHEL 8. Также библиотека GreenplumPython требует, чтобы расширение plpython3 было установлено в базе данных Greenplum, о чем мы упоминали в самом начале этой статьи. В качестве дополнительной зависимости для plpython библиотека GreenplumPython использует dill – пакет, который расширяет модуль pickle для сериализации и десериализации Python-объектов, предоставляя пользователю тот же интерфейс и некоторые дополнительные функции, включая возможность сохранять состояние сеанса интерпретатора в одной команде.
Что касается сходства GreenplumPython с pandas, эти Python-библиотеки имеют совершенно разные цели: GreenplumPython представляет собой интерфейс к удаленной СУБД, а pandas — это библиотека для управления локальными данными в памяти. Тем не менее, базовая структура данных GreenplumPython датафрейм (DataFrame) принципиально похожа на Dataframe в pandas, т.к. данные тоже организованы в строки и столбцы, которые могут быть разных типов и доступны по имени, а строки имеют один и тот же тип и являются итерируемыми.
Таким образом, GreenplumPython предоставляет API DataFrame, подобный pandas, который знаком большинству дата-аналитиков и специалистов по Data Science, а также позволяет выполнять с помощью UDF-функций сложную аналитику больших данных, поддерживая машинное обучение, Deep Learning, NLP и статистический анализ данных, непосредственно в Greenplum, без их переноса на локальную машину. Эталонный бенчмаркинговый тест TPC-H на 22 запросах к базе данных показал высокую эффективность и производительность этой бесплатной библиотеки, которую можно установить с помощью обычной команды install и менеджера пакетов pip3:
pip3 install greenplum-python
Узнайте больше подробностей про администрирование и эксплуатацию Greenplum с Arenadata DB для эффективного хранения и аналитики больших данных на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
Источники
- https://greenplum.org/introduction-to-greenplumpython-in-database-processing-of-billions-of-rows-with-python/
- https://greenplum-db.github.io/GreenplumPython/stable/index.html
- https://greenplum.org/how-to-implement-tpc-h-queries-with-greenplumpython/
- https://docs.vmware.com/en/VMware-Tanzu-Greenplum/7/greenplum-database/GUID-analytics-pl_python.html#pip39