Мені просто цікаво, в чому різниця між RDD
і DataFrame
(Spark 2.0.0 DataFrame - це псевдонім простого типу Dataset[Row]
) у Apache Spark?
Чи можете ви перетворити одне на інше?
Мені просто цікаво, в чому різниця між RDD
і DataFrame
(Spark 2.0.0 DataFrame - це псевдонім простого типу Dataset[Row]
) у Apache Spark?
Чи можете ви перетворити одне на інше?
Відповіді:
A DataFrame
добре визначено з пошуковим пошуком Google для "визначення DataFrame":
Кадр даних - це таблиця або двовимірна структура, схожа на масив, в якій кожен стовпець містить вимірювання на одній змінній, а кожен рядок містить один випадок.
Отже, a DataFrame
має додаткові метадані завдяки своєму табличному формату, що дозволяє Spark запускати певні оптимізації за остаточним запитом.
RDD
, З іншого боку, це всього лише R esilient D istributed D ataset , що в більшій мірі Blackbox даних , які не можуть бути оптимізовані , як операції , які можуть бути виконані проти нього, не так обмежений.
Однак ви можете перейти від DataFrame до RDD
via через його rdd
метод, а ви можете перейти від a RDD
до a DataFrame
(якщо RDD у табличному форматі) за допомогою toDF
методу
Загалом рекомендується використовувати, DataFrame
де це можливо, завдяки вбудованій оптимізації запитів.
Перше, що
DataFrame
було розвинене зSchemaRDD
.
Так .. конверсія між Dataframe
і RDD
абсолютно можлива.
Нижче наведено кілька фрагментів зразкового коду.
df.rdd
є RDD[Row]
Нижче наведено кілька варіантів створення фрейму даних.
1) yourrddOffrow.toDF
перетворюється на DataFrame
.
2) Використання createDataFrame
контексту sql
val df = spark.createDataFrame(rddOfRow, schema)
де схема може бути з деякими з варіантів нижче , як описано хорошим SO пост ..
Час від Scala класу і Reflection API сходиimport org.apache.spark.sql.catalyst.ScalaReflection val schema = ScalaReflection.schemaFor[YourScalacaseClass].dataType.asInstanceOf[StructType]
АБО за допомогою
Encoders
import org.apache.spark.sql.Encoders val mySchema = Encoders.product[MyCaseClass].schema
як описано у схемі, також можна створити за допомогою
StructType
іStructField
val schema = new StructType() .add(StructField("id", StringType, true)) .add(StructField("col1", DoubleType, true)) .add(StructField("col2", DoubleType, true)) etc...
Насправді зараз є 3 API Apache Spark ..
RDD
API:
RDD
(Еластичні Розподілена Dataset) API був в Спарк з моменту випуску 1.0.
RDD
API надає безліч методів трансформації, такі якmap
(),filter
() іreduce
() для виконання обчислень над даними. Кожен з цих методів призводить до нового, щоRDD
представляє перетворені дані. Однак ці методи просто визначають операції, які слід виконати, і перетворення не виконуються, поки не буде викликаний метод дії. Прикладами методів дії єcollect
() таsaveAsObjectFile
().
Приклад RDD:
rdd.filter(_.age > 21) // transformation
.map(_.last)// transformation
.saveAsObjectFile("under21.bin") // action
Приклад: Фільтр за атрибутом за допомогою RDD
rdd.filter(_.age > 21)
DataFrame
APISpark 1.3 представив новий
DataFrame
API в рамках ініціативи Project Tungsten, яка спрямована на підвищення ефективності та масштабованості Spark. УDataFrame
вводить API поняття схеми для опису даних, що дозволяє Спарк управляти схемою і передавати тільки дані між вузлами, в набагато більш ефективним способом , ніж при використанні Java сериализации.
DataFrame
API радикально відрізняється відRDD
API , тому що це API для побудови реляційної плану запиту , що Catalyst оптимізатор іскри з може потім виконати. API природний для розробників, які знайомі з планами запитів на будівництво
Приклад стилю SQL:
df.filter("age > 21");
Обмеження: Оскільки код посилається на атрибути даних за назвою, компілятор не може зафіксувати помилки. Якщо імена атрибутів невірні, помилка буде виявлена лише під час виконання, коли буде створений план запиту.
Іншим недоліком DataFrame
API є те, що він дуже орієнтований на масштаби і хоча він підтримує Java, підтримка обмежена.
Наприклад, під час створення DataFrame
з існуючих RDD
об’єктів Java оптимізатор каталізатора Spark не може зробити висновок про схему і передбачає, що будь-які об'єкти в DataFrame реалізують scala.Product
інтерфейс. Scala case class
розробляє поле, оскільки вони реалізують цей інтерфейс.
Dataset
API
Dataset
API, випущений в якості API попереднього перегляду в Спарк 1.6, прагне забезпечити найкраще з обох світів; знайомий об'єктно-орієнтований стиль програмування та безпека типуRDD
API для компіляції, але з перевагами продуктивності оптимізатора запитів Catalyst. Набори даних також використовують той же ефективний механізм зберігання поза нагромадженням, що іDataFrame
API.Що стосується серіалізації даних,
Dataset
API має концепцію кодерів, які перекладають між представленнями (об'єктами) JVM та внутрішнім бінарним форматом Spark. Spark має вбудовані кодери, які дуже вдосконалені тим, що вони генерують байтовий код для взаємодії з позабірними даними та надання доступу за запитом до окремих атрибутів без необхідності десериалізації цілого об'єкта. Spark ще не надає API для впровадження користувацьких кодерів, але це планується для майбутнього випуску.Крім того,
Dataset
API призначений для однакової роботи як з Java, так і з Scala. Працюючи з об’єктами Java, важливо, щоб вони повністю відповідали сумісності.
Приклад Dataset
стилю API SQL:
dataset.filter(_.age < 21);
Оцінки різні. між DataFrame
& DataSet
:
Течія рівня каталістів. . (Демістифікація презентації DataFrame та набору даних із саміту іскри)
Далі читайте ... статтю зі статтями даних - Казка про три Apache Spark API: RDD vs DataFrames і набори даних
df.filter("age > 21");
це можна оцінити / проаналізувати лише під час виконання. з моменту його рядка. У випадку наборів даних, набори даних відповідають сумісності. тому вік є власністю бобів. якщо властивості віку немає у вашому бобі, ви дізнаєтесь про це рано, тобто за час компіляції (тобто dataset.filter(_.age < 21);
). Помилка аналізу може бути перейменована як помилки оцінювання.
Apache Spark надають три типи API
Ось порівняння API між RDD, Dataframe та набором даних.
Основна абстракція, яку надає Spark, - це стійкий розподілений набір даних (RDD), який представляє собою сукупність елементів, розподілених по вузлах кластера, якими можна керувати паралельно.
Розподілена колекція:
RDD використовує операції MapReduce, які широко використовуються для обробки та генерації великих наборів даних з паралельним розподіленим алгоритмом на кластері. Це дозволяє користувачам писати паралельні обчислення, використовуючи набір операторів високого рівня, не турбуючись про розподіл роботи та відмовостійкість.
Незмінний: RDD, що складається з колекції записів, які розділені на частини. Розділ є базовою одиницею паралелізму в RDD, і кожен розділ - це один логічний поділ даних, який є незмінним і створюється за допомогою деяких перетворень на існуючих розділах. Незмінність допомагає досягти послідовності в обчисленнях.
Толерантність до помилок: Якщо ми втрачаємо деякий розділ RDD, ми можемо відтворити перетворення на цьому розділі в родовому рядку, щоб зробити те саме обчислення, а не робити реплікацію даних у кількох вузлах. Ця характеристика є найбільшою перевагою RDD, оскільки це економить багато зусиль в управлінні та реплікації даних і тим самим досягаються більш швидкі обчислення.
Ледачі оцінки: Усі перетворення в Spark ліниві, оскільки вони не підраховують свої результати одразу. Натомість вони просто запам'ятовують перетворення, застосовані до деякого базового набору даних. Перетворення обчислюються лише тоді, коли дія вимагає повернення результату в програму драйверів.
Функціональні перетворення: RDD підтримують два типи операцій: перетворення, які створюють новий набір даних із наявного, та дії, які повертають значення драйверній програмі після запуску обчислення на наборі даних.
Формати обробки даних:
Він може легко та ефективно обробляти структуровані дані, а також неструктуровані дані.
Мови програмування підтримуються:
RDD API доступний на Java, Scala, Python та R.
Немає вбудованої системи оптимізації: Працюючи зі структурованими даними, RDD не можуть скористатися передовими оптимізаторами Spark, включаючи оптимізатор каталізаторів та механізм виконання вольфраму. Розробникам необхідно оптимізувати кожен RDD на основі його атрибутів.
Обробка структурованих даних: На відміну від Dataframe та наборів даних, RDD не виводить схему введених даних і вимагає від користувача вказати їх.
Spark представив Dataframes у випуску Spark 1.3. Рамка даних долає ключові проблеми, з якими стикалися RDD.
DataFrame - це розподілений набір даних, організований у названі стовпці. Це концептуально еквівалентно таблиці в реляційній базі даних або R / Python Dataframe. Поряд з Dataframe Spark також представив оптимізатор каталізаторів, який використовує розширені функції програмування для побудови розширюваного оптимізатора запитів.
Розподілена колекція об'єкта рядків: DataFrame - це розподілений набір даних, організований у названі стовпці. Він концептуально еквівалентний таблиці в реляційній базі даних, але з більш багатими оптимізаціями під капотом.
Обробка даних: Обробка структурованих та неструктурованих форматів даних (Avro, CSV, еластичний пошук та Кассандра) та систем зберігання даних (HDFS, таблиці HIVE, MySQL тощо). Він може читати і писати з усіх цих різних джерел даних.
Оптимізація за допомогою оптимізатора каталізаторів: вона забезпечує як SQL запити, так і API DataFrame. Рамка даних використовує структуру перетворення дерева каталізатора в чотири фази,
1.Analyzing a logical plan to resolve references
2.Logical plan optimization
3.Physical planning
4.Code generation to compile parts of the query to Java bytecode.
Сумісність вуликів: Використовуючи Spark SQL, ви можете запускати незмінені запити Hive на своїх існуючих складах Hive. Він повторно використовує Five Frontend та MetaStore і дає вам повну сумісність з існуючими даними Hive та запитами та UDF.
Вольфрам: Вольфрам надає резервну копію фізичного виконання, яка явно управляє пам'яттю і динамічно генерує байт-код для оцінки вираження.
Мови програмування підтримуються:
API Dataframe доступний у Java, Scala, Python та R.
Приклад:
case class Person(name : String , age : Int)
val dataframe = sqlContext.read.json("people.json")
dataframe.filter("salary > 10000").show
=> throws Exception : cannot resolve 'salary' given input age , name
Це особливо складно, коли ви працюєте з декількома кроками трансформації та агрегації.
Приклад:
case class Person(name : String , age : Int)
val personRDD = sc.makeRDD(Seq(Person("A",10),Person("B",20)))
val personDF = sqlContext.createDataframe(personRDD)
personDF.rdd // returns RDD[Row] , does not returns RDD[Person]
API набору даних - це розширення до DataFrames, що забезпечує безпечний для об'єктів орієнтований на об'єкт інтерфейс програмування. Це сильно типізована, незмінна колекція об'єктів, які відображені у реляційній схемі.
В основі набору даних API - це нова концепція, що називається кодером, який відповідає за перетворення між об'єктами JVM та табличне представлення. Табличне подання зберігається з використанням внутрішнього двійкового формату вольфраму Spark, що дозволяє виконувати операції над серіалізованими даними та покращувати використання пам'яті. Spark 1.6 постачається з підтримкою автоматичного генерування кодерів для найрізноманітніших типів, включаючи примітивні типи (наприклад, String, Integer, Long), регістрові класи Scala та Java Beans.
Забезпечує найкращі як RDD, так і Dataframe: RDD (функціональне програмування, безпечний тип), DataFrame (реляційна модель, оптимізація запитів, виконання вольфраму, сортування та переміщення)
Енкодери: За допомогою Encoders легко перетворити будь-який об’єкт JVM в набір даних, що дозволяє користувачам працювати як зі структурованими, так і з неструктурованими даними на відміну від Dataframe.
Мови програмування підтримуються: API наборів даних наразі доступний лише у Scala та Java. Наразі Python та R не підтримуються у версії 1.6. Підтримка Python призначена для версії 2.0.
Тип безпеки: API наборів даних забезпечує безпеку часу компіляції, яка не була доступна в Dataframes. У наведеному нижче прикладі ми можемо побачити, як Набір даних може оперувати доменними об’єктами за допомогою компіляції лямбда-функцій.
Приклад:
case class Person(name : String , age : Int)
val personRDD = sc.makeRDD(Seq(Person("A",10),Person("B",20)))
val personDF = sqlContext.createDataframe(personRDD)
val ds:Dataset[Person] = personDF.as[Person]
ds.filter(p => p.age > 25)
ds.filter(p => p.salary > 25)
// error : value salary is not a member of person
ds.rdd // returns RDD[Person]
Приклад:
ds.select(col("name").as[String], $"age".as[Int]).collect()
Немає підтримки для Python та R: На початок випуску 1.6 набори даних підтримують лише Scala та Java. Підтримка Python буде представлена в Spark 2.0.
API наборів даних приносить ряд переваг перед існуючим API RDD та Dataframe з кращою безпекою типу та функціональним програмуванням. З викликом вимог до кастингу типів в API ви все одно не будете вимагати безпеки типу і зробите ваш код крихким.
Dataset
не є LINQ, а лямбда-вираз не може бути інтерпретований як дерева виразів. Тому є чорні скриньки, і ви втрачаєте майже всі переваги (якщо не всі) оптимізатора. Лише невеликий набір можливих недоліків: Spark 2.0 Dataset vs DataFrame . Крім того, лише повторити щось, про що я заявляв кілька разів - в цілому перевірка типу "кінця до кінця" неможлива за допомогою Dataset
API. Приєднання - лише найвизначніший приклад.
RDD
RDD
являє собою збір елементів, що мають стійкість до відмов, якими можна керувати паралельно.
DataFrame
DataFrame
це набір даних, організований у названі стовпці. Це концептуально еквівалентно таблиці в реляційній базі даних або кадру даних в R / Python, але з більш багатими оптимізаціями під кришкою .
Dataset
Dataset
це розподілений збір даних. Набір даних - це новий інтерфейс, доданий у Spark 1.6, який надає переваги RDD (сильний набір тексту, можливість використовувати потужні лямбда-функції) з перевагами оптимізованого механізму виконання Spark SQL .
Примітка:
Набір даних рядків (
Dataset[Row]
) у Scala / Java часто називатиметься DataFrames .
Nice comparison of all of them with a code snippet.
Питання: Чи можете ви перетворити один на інший, як RDD в DataFrame, або навпаки?
1. RDD
до DataFrame
с.toDF()
val rowsRdd: RDD[Row] = sc.parallelize(
Seq(
Row("first", 2.0, 7.0),
Row("second", 3.5, 2.5),
Row("third", 7.0, 5.9)
)
)
val df = spark.createDataFrame(rowsRdd).toDF("id", "val1", "val2")
df.show()
+------+----+----+
| id|val1|val2|
+------+----+----+
| first| 2.0| 7.0|
|second| 3.5| 2.5|
| third| 7.0| 5.9|
+------+----+----+
більше способів: Перетворення об’єкта RDD в Dataframe в Spark
2. DataFrame
/ DataSet
до RDD
з .rdd()
методом
val rowsRdd: RDD[Row] = df.rdd() // DataFrame to RDD
Оскільки DataFrame
він набраний слабко, а розробники не отримують переваг типової системи. Наприклад, скажімо, що ви хочете прочитати щось із SQL і запустити на ньому деяку агрегацію:
val people = sqlContext.read.parquet("...")
val department = sqlContext.read.parquet("...")
people.filter("age > 30")
.join(department, people("deptId") === department("id"))
.groupBy(department("name"), "gender")
.agg(avg(people("salary")), max(people("age")))
Коли ви говорите people("deptId")
, ви не отримуєте назад Int
або а Long
, ви отримуєте назад Column
об’єкт, над яким вам потрібно працювати. У мовах із системами багатого типу, такими як Scala, ви втрачаєте всю безпеку типу, що збільшує кількість помилок під час виконання речей, які можуть бути виявлені під час компіляції.
Навпаки, DataSet[T]
набирається. коли ти робиш:
val people: People = val people = sqlContext.read.parquet("...").as[People]
Ви насправді повертаєте People
об'єкт, де deptId
є фактичним інтегральним типом, а не типом стовпця, таким чином, використовуючи перевагу системи типів.
Станом на Spark 2.0, API DataFrame та DataSet будуть уніфіковані, де DataFrame
буде псевдонім типу DataSet[Row]
.
DataFrame
- уникнути порушення API. У всякому разі, просто хотілося це вказати. Дякую за редагування та репутацію.
Просто RDD
є основним компонентом, але DataFrame
це API, що вводиться в іскрі 1.30.
Збір розділів даних називається RDD
. Вони RDD
повинні дотримуватися кількох властивостей, таких як:
Тут RDD
або структуровано, або неструктуровано.
DataFrame
є API, доступним у Scala, Java, Python та R. Він дозволяє обробляти будь-який тип Структурованих та напівструктурованих даних. Для визначення DataFrame
колекція розподілених даних, організованих у названі стовпці, називається DataFrame
. Ви можете легко оптимізувати RDDs
в DataFrame
. Ви можете обробляти дані JSON, дані про паркет, дані HiveQL одночасно, використовуючи DataFrame
.
val sampleRDD = sqlContext.jsonFile("hdfs://localhost:9000/jsondata.json")
val sample_DF = sampleRDD.toDF()
Тут Sample_DF вважають як DataFrame
. sampleRDD
називається (необроблені дані) RDD
.
Більшість відповідей правильні, тут хочеться додати лише один пункт
У Spark 2.0 два API (DataFrame + DataSet) будуть об'єднані разом в єдиний API.
"Об'єднання DataFrame та набір даних: у Scala та Java DataFrame та Dataset є уніфікованими, тобто DataFrame - це лише псевдонім типу для Dataset of Row. У Python та R, зважаючи на відсутність безпеки типу, DataFrame є основним інтерфейсом програмування."
Набори даних схожі на RDD, однак, замість використання серіалізації Java або Kryo, вони використовують спеціалізований Енкодер для серіалізації об'єктів для обробки або передачі по мережі.
Spark SQL підтримує два різні методи перетворення існуючих RDD в набори даних. Перший метод використовує відображення для визначення схеми RDD, що містить конкретні типи об'єктів. Цей підхід, заснований на рефлексії, призводить до більш короткого коду і добре працює, коли ви вже знаєте схему під час написання програми Spark.
Другий метод створення наборів даних - це через програмний інтерфейс, який дозволяє побудувати схему, а потім застосувати її до існуючого RDD. Хоча цей метод є більш багатослівним, він дозволяє будувати набори даних, коли стовпці та їх типи не відомі до часу виконання.
Тут ви можете знайти RDD tof відповідь на розмову кадру даних
DataFrame еквівалентний таблиці в RDBMS і може також маніпулювати аналогічно до "рідних" розподілених колекцій в RDD. На відміну від RDD, Dataframes відслідковують схему та підтримують різні реляційні операції, що призводять до більш оптимізованого виконання. Кожен об'єкт DataFrame представляє логічний план, але через їх "ледачий" характер виконання не відбувається, поки користувач не викликає певну "операцію виводу".
Я сподіваюся, що це допомагає!
Кадр даних - це RDD об'єктів рядків, кожен з яких представляє запис. Рамка даних також знає схему (тобто поля даних) своїх рядків. Хоча Dataframes схожі на звичайні RDD, вони внутрішньо зберігають дані більш ефективно, користуючись їх схемою. Крім того, вони надають нові операції, недоступні для RDD, такі як можливість запускати SQL запити. Рамки даних можуть бути створені із зовнішніх джерел даних, з результатів запитів або з звичайних RDD.
Довідка: Zaharia M., et al. Навчальна іскра (O'Reilly, 2015)
Spark RDD (resilient distributed dataset)
:
RDD - це основний API абстрагування даних і доступний з самого першого випуску Spark (Spark 1.0). Це нижчий рівень API для управління розподіленим збором даних. API API RDD розкриває деякі надзвичайно корисні методи, які можна використовувати для отримання дуже жорсткого контролю над базовою фізичною структурою даних. Це незмінна (лише для читання) збірка розділених даних, що поширюються на різних машинах. RDD дозволяє обчислювати в пам'яті великі кластери, щоб прискорити обробку великих даних невідхильним чином. Для включення відмовостійкості RDD використовує DAG (направлений ациклічний графік), який складається з набору вершин і ребер. Вершини та ребра в DAG представляють RDD та операцію, яка повинна застосовуватися відповідно до цього RDD. Перетворення, визначені на RDD, ліниві і виконуються лише тоді, коли викликається дія
Spark DataFrame
:
Spark 1.3 представив два нові API абстрагування даних - DataFrame та DataSet. API DataFrame організовує дані в стовпці з назвою, як таблиця у реляційній базі даних. Це дозволяє програмістам визначати схему на розподіленому зборі даних. Кожен рядок у DataFrame є рядком типу об'єкта. Як і таблиця SQL, кожен стовпець повинен мати однакову кількість рядків у DataFrame. Коротше кажучи, DataFrame - це ліниво оцінений план, який визначає операції, які необхідно виконати над розподіленим збором даних. DataFrame - це також незмінна колекція.
Spark DataSet
:
Як розширення до API DataFrame, Spark 1.3 також представив API DataSet, який забезпечує суворо типований та об'єктно-орієнтований інтерфейс програмування в Spark. Це незмінне, безпечне для збору розподілених даних. Як і DataFrame, API DataSet також використовує двигун Catalyst для оптимізації виконання. DataSet - це розширення до API DataFrame.
Other Differences
-
DataFrame є РДД , який має схему. Ви можете розглядати це як таблицю реляційних баз даних, оскільки кожен стовпець має ім'я та відомий тип. Потужність DataFrames походить від того, що, коли ви створюєте DataFrame зі структурованого набору даних (Json, Parquet ..), Spark може зробити схему, зробивши перехід на весь набір даних (Json, Parquet ..), що завантажується. Тоді при розрахунку плану виконання Spark може використовувати схему і робити значно кращі оптимізації обчислень. Зауважте, що DataFrame називався SchemaRDD перед Spark v1.3.0
Spark RDD -
RDD означає стійкий розподілений набір даних. Це колекція записів для розділів лише для читання. RDD - це основна структура даних Spark. Це дозволяє програмісту виконувати обчислення в пам'яті на великих кластерах з відмовою. Таким чином, пришвидшити завдання.
Іскровий кадр даних -
На відміну від RDD, дані, організовані в іменовані стовпці. Наприклад таблиця у реляційній базі даних. Це незмінний розподілений збір даних. DataFrame in Spark дозволяє розробникам нав'язувати структуру розподіленому набору даних, що дозволяє абстрагуватися на більш високому рівні.
Іскровий набір даних -
Набори даних у Apache Spark - це розширення API DataFrame, який забезпечує безпечний для об'єктів орієнтований на об'єкти інтерфейс програмування. Набір даних використовує переваги оптимізатора каталізаторів Spark, відкриваючи вирази та поля даних планувальнику запитів.
Усі чудові відповіді та використання кожного API мають певні вигоди. Набір даних створений як супер API для вирішення багатьох проблем, але багато разів RDD як і раніше працює найкраще, якщо ви розумієте свої дані та якщо алгоритм обробки оптимізований для того, щоб робити багато речей за один пропуск до великих даних, тоді RDD здається найкращим варіантом.
Агрегація за допомогою API набору даних все ще споживає пам'ять і з часом буде покращуватися.