Добавить UUID в набор данных Spark

Я пытаюсь добавить столбец UUID в свой набор данных.

getDataset(Transaction.class)).withColumn("uniqueId", functions.lit(UUID.randomUUID().toString())).show(false);

Но в результате все строки имеют одинаковый UUID. Как я могу сделать его уникальным?

+-----------------------------------+
uniqueId                            |
+----------------+-------+-----------
|1abdecf-8303-4a4e-8ad3-89c190957c3b|
|1abdecf-8303-4a4e-8ad3-89c190957c3b|
|1abdecf-8303-4a4e-8ad3-89c190957c3b|
|1abdecf-8303-4a4e-8ad3-89c190957c3b|
|1abdecf-8303-4a4e-8ad3-89c190957c3b|
|1abdecf-8303-4a4e-8ad3-89c190957c3b|
|1abdecf-8303-4a4e-8ad3-89c190957c3b|
|1abdecf-8303-4a4e-8ad3-89c190957c3b|
|1abdecf-8303-4a4e-8ad3-89c190957c3b|
|1abdecf-8303-4a4e-8ad3-89c190957c3b|
----------+----------------+--------+

person Adiant    schedule 09.04.2018    source источник
comment
Проверьте ссылку ниже uuid-generator?rq=1" title="добавить новый столбец в новый столбец фрейма данных. Я хочу, чтобы он был генератором uuid"> stackoverflow.com/questions/37231616/   -  person D-2020365    schedule 09.04.2018
comment
Нет, я попробовал решение по ссылке, оно использует lit, что не является правильным решением.   -  person Adiant    schedule 09.04.2018


Ответы (1)


Когда вы включаете UUID в качестве столбца lit, вы делаете то же самое, что и включение строкового литерала.

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

Лучше всего создать столбец с функция Spark rand и использование UUID.nameUUIDFromBytes для преобразования ее в UUID.

Изначально у меня было:

val uuid = udf(() => java.util.UUID.randomUUID().toString)
getDataset(Transaction.class).withColumn("uniqueId", uuid()).show(false);

что, как указал @irbull, может быть проблемой.

person Benjamin Manns    schedule 09.04.2018
comment
Большое спасибо Бенджамин. Это решение работает. В Java создание UDF немного более утомительно. UDF необходимо создать зарегистрированное объявление, как показано ниже: static UDF1 uniqueId= types -> UUID.randomUUID().toString(); sparkSession.udf().register(uId, режим, DataTypes.StringType); - person Adiant; 10.04.2018
comment
У этого решения есть две проблемы. 1. Уникальность UUID.randomUUID() не гарантируется для разных узлов. Он использует псевдослучайное число, что хорошо на одной машине, но в кластерной среде могут возникнуть коллизии. 2. Пользовательские функции должны быть детерминированными. То есть для одного и того же ввода вы получаете один и тот же вывод (spark оставляет за собой право кэшировать, повторно использовать результаты и т. д.) или вызывать один и тот же метод несколько раз, если он того пожелает. stackoverflow .com/questions/42960920/ - person irbull; 14.06.2018
comment
Отличный момент @irbull - я обновлю, чтобы отразить. - person Benjamin Manns; 14.06.2018
comment
@irbull, тогда что было бы хорошим способом генерировать новые уникальные идентификаторы при добавлении строк в фрейм данных? monotonically_increasing_id + last stored monotonically_increasing_id? - person Mehdi; 27.01.2019
comment
это генерирует уникальный идентификатор для каждой строки. - person Priyanshu Singh; 23.01.2020
comment
Просто чтобы убедиться, что использование monotonically_increasing_id с настраиваемой логикой для добавления последнего максимального значения не будет работать, поскольку монотонно увеличивающийся идентификатор рассчитывается на основе номера раздела и строки, поэтому один и тот же кадр данных может иметь значения от 0 до 100 и от 854654 до 854659. - person aweis; 20.02.2020
comment
Достаточно интересно, что в Spark SQL есть поддержка этого issues.apache.org/jira/browse/SPARK. -23599 Детерминированным образом между повторными попытками. - person Jelmer; 30.03.2020
comment
Это очень медленное решение, и есть намного более простое решение: у Spark есть собственная функция uuid. UDF плохо влияют на искровой код — они являются золотым молотом искрового кодирования. - person Marco; 07.07.2021