Greenplum + Python: обзор расширения

обучение Greenplum курсы примеры для разработчиков, Greenplum для инженеров данных, Greenplum дата-инженер курсы обучение, Greenplum Python курсы примеры обучение, обучение большим данным, Школа Больших Данных Учебный Центр Коммерсант

Как писать UDF-функции Greenplum на Python: краткий обзор расширения PL/Python для дата-инженера и разработчика распределенных приложений. Как его установить, настроить и использовать: сопоставления типов данных, SQL-запросы, модули и функции.

Поддержка Python в MPP-СУБД

Поскольку освоить Python намного проще других языков программирования, например, Java или C#, неудивительно, что он сегодня очень популярен. Этот процедурный язык программирования поддерживается множеством сред разработки и исполнения программ, а также различными СУБД. Масштабируемая MPP-СУБД Greenplum (GP) тоже поддерживает Python с помощью соответствующего расширения PL/Python. Оно позволяет писать пользовательские функции базы данных Greenplum на языке Python, чтобы быстро создавать приложения, используя готовые библиотеки и модули. Можно запускать блоки кода PL/Python как анонимные блоки кода.

Это расширение по умолчанию устанавливается вместе с базой данных Greenplum, включая версию Python и PL/Python. В рамках установки Greenplum пользовательская среда gpadmin настраивается на использование Python, установленного вместе с базой данных. Примечательно, что GP предоставляет набор Python-библиотек для Data Science, которые можно использовать с языком PL/Python.

Чтобы создать и запустить UDF-функцию PL/Python в базе данных, нужно зарегистрировать язык в GP. Это следует сделать для каждой базы данных с помощью SQL-команды CREATE EXTENSION, запущенной от имени суперпользователя.

Для базы данных, где не нужен PL/Python, можно удалить его поддержку с помощью SQL-команды DROP EXTENSION, также запущенной от имени суперпользователя. Команда по умолчанию завершается ошибкой, если какие-либо существующие объекты или функции зависят от языка. Чтобы удалить все зависимые объекты, включая функции, созданные с помощью PL/Python, следует в команде DROP EXTENSION указать параметр CASCADE.

Разработка UDF-функций Greenplum на PL/Python

Тело определяемой пользователем функции PL/Python представляет собой Python-скрипт. При вызове функции ее аргументы передаются как элементы массива args[], а именованные аргументы передаются Python-скрипту как обычные переменные. Результат возвращается функцией PL/Python с оператором return или оператором yield в случае набора строк.

Пустое значение (None) переводится в Null-значение SQL. Когда UDF возвращает логический тип данных, Greenplum оценивает возвращаемое значение на предмет истинности в соответствии с правилами Python: 0 и пустая строка являются ложными, а «f» будет истинным. Сопоставление типов данных показано в таблице.

Примитивные типы данных Greenplum

Типы данных Python

boolean

bool

bytea (binary data, byte array)

bytes

smallint, bigint, oid

int

real, double

float

numeric

decimal

other primitive types

string

SQL null value

None

Передать массив значений SQL в функции PL/Python можно через список Python. Аналогично, функции PL/Python возвращают значения массива SQL в виде списка Python. Указать массив в PL/Python можно с помощью символов []. PL/Python рассматривает многомерные массивы как списки списков: передать многомерный массив функции PL/Python можно, используя вложенные списки Python. Когда функция PL/Python возвращает многомерный массив, все внутренние списки на каждом уровне должны иметь одинаковый размер.

PL/Python также принимает другие последовательности Python, такие как кортежи, в качестве аргументов функций для обратной совместимости с версиями Greenplum, где не поддерживаются многомерные массивы. В таких случаях последовательности Python всегда обрабатываются как одномерные массивы, поскольку они неоднозначны для составных типов данных.

Передать аргументы составного типа в функцию PL/Python можно, используя сопоставления Python. Имена элементов сопоставления являются именами атрибутов составных типов. Если атрибут имеет Null-значение, оно сопоставляется как None.

Можно вернуть результат составного типа как тип последовательности (кортеж или список), указав составной тип как кортеж, а не список в многомерном массиве. Примечательно, что нельзя вернуть массив составных типов в виде списка из-за неоднозначности определения, представляет ли список составной тип или это лишь другое измерение массива. Кортежи составного типа указываются с помощью символов (). Аналогичным образом, функция Python может возвращать набор скалярных или составных типов из любого типа последовательности: кортеж, список, набор.

SQL-запросы и модули PL/Python

Модуль PL/Python plpy предоставляет две функции Python для запуска SQL-запроса и подготовки плана выполнения запроса: plpy.execute и plpy.prepare(). Подготовка плана выполнения SQL-запроса полезна, если он запускается из нескольких Python-функций. PL/Python также поддерживает функцию plpy.subtransaction(), помогающую управлять вызовами plpy.execute() в явной подтранзакции.

Вызов plpy.execute() со строкой запроса и необязательным аргументом limit приводит к выполнению запроса и возврату результата в Python-объекте, который эмулирует объект списка или словаря. Доступ к строкам, возвращенным в объекте результата, можно получить по номеру строки и имени столбца. Нумерация строк набора результатов начинается с 0. Объект результата является изменяемым и имеет следующие дополнительные методы:

  • nrows — количество строк, возвращенных запросом;
  • status — возвращаемое значение SPI_execute().

Например, этот Python-оператор в UDF-функции PL/Python выполняет SQL-запрос выбора первых 5 строк из таблицы my_table: rv = plpy.execute(«SELECT * FROM my_table», 5)

Набор результатов хранится в объекте rv. Если в таблице my_table есть столбец my_column, доступ к нему будет следующим: my_col_data = rv[i][«my_column»]

Поскольку в рассматриваемом случае функция plpy.execute() возвращает максимум 5 строк, индекс i может быть целым числом от 0 до 4.

Функция plpy.prepare() подготавливает план выполнения запроса и вызывается со строкой запроса и списком типов параметров, если в запросе есть ссылки на них. Например, следующий оператор готовит план выполнения UDF-функции PL/Python для SQL-запроса фильтрации фамилии пользователей (last_name) из таблицы my_users по заданному условию:

plan = plpy.prepare(«SELECT last_name FROM my_users WHERE   first_name = $1», [ «text» ])

Здесь строковый текст — это тип данных переменной, которая передается для значения условия $1. После подготовки плана выполнения SQL-запроса можно использовать функцию plpy.execute() для его запуска: rv = plpy.execute(plan, [ «Ann» ], 5)

По аналогии с limit, третий аргумент означает предел количества возвращаемых строк и является необязательным. Подготовленный план выполнения SQL-запроса с помощью модуля PL/Python автоматически сохраняется. Чтобы эффективно использовать сохраненные планы при вызовах UDF-функций, можно использовать один из словарей постоянного хранилища Python SD или GD.

Глобальный словарь SD доступен для хранения данных между вызовами функций и является общедоступными данными, доступными для всех функций Python в рамках сеанса. Поэтому использовать глобальный словарь следует с осторожностью.

Каждая функция получает свою собственную среду выполнения в интерпретаторе Python. Например, глобальные данные и аргументы функции из myfunc недоступны для myfunc2. Исключением являются данные в словаре GD.

CREATE FUNCTION usesavedplan() RETURNS trigger AS $$
  if SD.has_key("plan"):
    plan = SD["plan"]
  else:
    plan = plpy.prepare("SELECT 1")
    SD["plan"] = plan

  # rest of function
$$ LANGUAGE plpythonu;

С точки зрения производительности импорт модуля Python является дорогостоящей операцией и может снизить скорость выполнения программы. При частом применении одного и того же модуля можно использовать глобальные переменные Python для его загрузки при первом вызове, чтобы не требовать его импорта при последующих вызовах. К примеру, следующая функция PL/Python использует словарь постоянного хранилища GD, чтобы избежать импорта модуля, если он уже был импортирован и находится в GD:

psql=#
   CREATE FUNCTION pytest() returns text as $$ 
      if 'mymodule' not in GD:
        import mymodule
        GD['mymodule'] = mymodule
    return GD['mymodule'].sumd([1,2,3])
$$;

 

Модуль Python plpy реализует следующие функции для управления ошибками и сообщениями:

  • debug
  • log
  • info
  • notice
  • warning
  • error
  • fatal
  • debug

Функции сообщений plpy.error() и plpy.fatal() вызывают исключение Python, которое, если его не перехватить, распространяется на вызывающий запрос, вызывая отмену текущей транзакции или подтранзакции. Эти функции могут иметь сообщение в качестве аргумента, смысл выполнения от этого не меняется. Другие функции сообщений генерируют только сообщения с разными уровнями приоритета. Как сообщения определенного приоритета передаются клиенту и записываются в журнал сервера, контролируется параметрами конфигурации сервера Greenplum log_min_messages и client_min_messages.

При установке модуля Python в базу данных Greenplum он должен быть добавлен на всех хостах сегмента и зеркальных хостах в кластере. При расширении Greenplum следует добавить модули Python на узлы нового сегмента. Для этого можно использовать команды gpssh и gpscp, которые запустят утилиты копирования файлов на хостах Greenplum.

В заключение отметим несколько ограничений PL/Python:

  • Greenplum не поддерживает триггеры PL/Python;
  • PL/Python доступен только как ненадежный язык базы данных Greenplum, т.е. может быть установлен и деинсталлирован только суперпользователями;
  • обновляемые курсоры (UPDATE…WHERE CURRENT OF и..WHERE CURRENT OF) не поддерживаются.

Освойте практику администрирования и эксплуатации Greenplum и Arenadata DB для эффективного хранения и аналитики больших данных на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:

Я даю свое согласие на обработку персональных данных и соглашаюсь с политикой конфиденциальности.

Источники

  1. https://gpdb.docs.pivotal.io/6-20/analytics/pl_python.html

Поиск по сайту