Комментарии 20
Ну, допустим, а можно теперь эту кастомную функцию как-то заппакеджить и дать дата-сайнтистам, которые на PySpark в основном? Особенно, если речь идёт о облачных средах, таких как Databricks или Glue?
Интересный кейс. Спасибо! В рамках своих изысканий попробую.
Пока я хочу использовать подобноное для своих Spark-приложений.
Вполне, вам нужно сделать джарник с таким кодом, а потом его добавить в зависимость spark-приложения, как условный драйвер для БД.
А в коде просто сделать импорт.
Но если мы говорим, про pySpark, скорее всего придется сделать питон враппер или вызывать через jvm
Еще интересный юзкейс для исследования - как сделать доступной эту функцию из Датабриск ноутбука, в котором дата-сайентисты исползуют PySpark
Посмотрел, да это может сработать через Jar и врапперы. Как посоветовал mitgard, нужно упаковать Jar, затем его указывать в spark-submit --jars. Враппер будет иметь вид вроде такого
from pyspark.sql.column import Column
from pyspark.sql.functions import expr
def my_catalyst_expression(column):
return Column(expr(f"MyCatalystExpression({column._jc.toString()})"))
...
df.select(my_catalyst_expression(df.field)).show()
В случае databricks тогда все даже чуть проще, созданный Jar можно загрузить в Libraries у кластера.
Интересно!
Реализация генератора UUID с использованием UDF проста.
Я бы хотел отметить, что на самом деле все не всегда так просто, даже для такой простой функции. Дело в том, что UDF сериализуются и передаются в executors, это во-первых (ну, те кто программирует на спарке, уже должны это обычно знать).
Но тут еще могут добавляться вопросы с класслоадерами. Скажем, мы как-то попытались создать экземпляр UDF и зарегистрировать его в groovy скрипте, который динамически выполнялся из кода на спарке. Так вот, ничего не получилось, потому что класслоадер оказался другой, и наша функция имела сигнатуру, отличную от нужной. А как устроены класслоадеры в спарке, описано примерно так же, как описано создание catalyst выражений из этой статьи - т.е. примерно никак.
Да, про сериализацию верно подмечено. Плюсую
Offtop: Spark поддерживает Scala 3?
Нет, официально нет. Но есть способы заставить работать)
Насколько я помню - нет. Но - спарк 3.4 привнес Spark Connect - это API, сделанный с целью поддержать другие языки. Сами авторы ничего кроме стандартных Java Scala и Python c R не поддержали, но написать реализацию вроде можно. Для JVM based Scala 3 - уж наверняка. Т.е. у вас будет Dataset, скажем просто.
Недавно столкнулся и с удивлением узнал о возможности написания Spark-приложений на .NET: https://github.com/dotnet/spark
eval(input: InternalRow)
Ну вот хорошо что у автора 0-арная функция. А если мы заходим использовать аргументы? Я пытался как-то разобраться с expressions, но так и уперся в отсутствие документации, скажем, непонятно где вот эти InternalRow взять, и что с ними можно делать.
В рамках собственных "раскопок" мне уже удалось создать функцию 2х и 3х аргументов - на эту тему и хочу подготовить уже свою статью
О, давайте-давайте, будем ждать.
Ну куда копать, примерно понятно. Скажем, вот: https://books.japila.pl/spark-sql-internals/expressions/ScalaUDF/#one-argument-udf
Есть же исходники, по ним не понятно, что можно с данным классом делать?
https://github.com/apache/spark/blob/b623601910a37c863edac56d18e79a44b93c5b36/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/InternalRow.scala#L34
Спасибо автору за перевод
[Перевод] Почему стоит начать писать собственные Spark Native Functions?