Узнать, равны ли 2 таблицы (`tbl_spark`), не собирая их с помощью sparklyr

Учтите, что в spark есть 2 таблицы или ссылки на таблицы, которые вы хотите сравнить, например. чтобы убедиться, что ваша резервная копия работала правильно. Есть ли возможность сделать этот пульт в искре? Потому что бесполезно копировать все данные в R с помощью collect().

library(sparklyr)
library(dplyr)
library(DBI)

##### create spark connection here
# sc <- spark_connect(<yourcodehere>)
spark_connection(sc)
spark_context(sc)

trees1_tbl <- sdf_copy_to(sc, trees, "trees1")
trees2_tbl <- sdf_copy_to(sc, trees, "trees2")
identical(trees1_tbl, trees2_tbl) # FALSE
identical(collect(trees1_tbl), collect(trees2_tbl)) # TRUE
setequal(trees1_tbl, trees2_tbl) # FALSE
setequal(collect(trees1_tbl), (trees2_tbl)) # TRUE

spark_disconnect(sc)

Было бы неплохо, если бы dplyr::setequal() можно было использовать напрямую.


person nachti    schedule 26.07.2018    source источник


Ответы (3)


Это просто не сработает. Здесь важно помнить, что Spark DataFrames* не является контейнером данных. Есть описания преобразований, которые будут применяться к данным после выполнения конвейера. Это означает, что результат может быть разным каждый раз, когда вы оцениваете данные. Единственный осмысленный вопрос, который вы можете здесь задать, заключается в том, описывают ли оба DataFrames один и тот же план выполнения, что, очевидно, бесполезно в вашем случае.

Итак, как сравнить данные? Здесь действительно нет универсального ответа.

Тестирование

Если это часть модульного теста, сбор данных и сравнение локальных объектов — это то, что нужно (хотя имейте в виду, что использование наборов может упустить некоторые тонкие, но распространенные проблемы).

Производство

Внешний модульный тест вы можете попробовать проверить, если

  • Размер А равен размеру В
  • A ЗА ИСКЛЮЧЕНИЕМ B ЕСТЬ ∅ И B ЗА ИСКЛЮЧЕНИЕМ A ЕСТЬ ∅

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

В простейшем случае вы можете вручную проверить основные инварианты, такие как количество прочитанных и записанных строк, с помощью веб-интерфейса Spark. Для более расширенного мониторинга вы можете реализовать свои собственные прослушиватели Spark (например, проверьте Spark: как получить количество записанных строк?), прослушиватели запросов или аккумуляторы, но все эти компоненты не представлены в sparklyr и потребуют написания собственного (Scala или Java) кода.


* Я имею в виду Spark, но использование dplyr с серверной частью базы данных не так уж отличается.

person zero323    schedule 26.07.2018

Я написал пример того, как я думаю, что вы можете это сделать. По сути, вам просто нужно объединить обе таблицы, а после этого просто применить метод Different() к результату объединения. После different() просто сравните количество строк результирующего фрейма данных с начальным количеством строк.

>>> rdd = spark.sparkContext.parallelize([("test","test1")])
>>> rdd.collect()
[('test', 'test1')]
>>> df1 = spark.createDataFrame(rdd).toDF("col1","col2")
>>> df1.show()
+----+-----+
|col1| col2|
+----+-----+
|test|test1|
+----+-----+

>>> df2 = spark.createDataFrame(rdd).toDF("col1","col2")
>>> df2.show()
+----+-----+
|col1| col2|
+----+-----+
|test|test1|
+----+-----+

>>> df3 = df1.union(df2)
>>> df3.show()
+----+-----+
|col1| col2|
+----+-----+
|test|test1|
|test|test1|
+----+-----+

>>> df3.distinct().show()
+----+-----+
|col1| col2|
+----+-----+
|test|test1|
+----+-----+

>>> df1.count()
1
>>> df3.distinct().count()
1
person Cosmin    schedule 23.10.2018

Спасибо @Cosmin за подсказку!

Сначала используйте setdiff(), у которого есть метод для tbl_lazy-объектов, предоставленный dplyr (в отличие от setequal), подсчитайте строки и сравните их с 0.

trees1_tbl %>% setdiff(trees2_tbl) %>% sdf_nrow() == 0
## TRUE

Результатом будет TRUE, если все данные из trees1_tbl содержатся в trees2_tbl. Если они различаются, можно опустить == 0, чтобы получить количество строк, отсутствующих в trees2_tbl.

person nachti    schedule 31.10.2018