Apache Spark:資料框,資料集和RDD之間的區別 - Baeldung
Apache Spark是一個快速的分散式資料處理系統。它執行記憶體中的資料處理,並使用記憶體中的快取和最佳化的執行,從而實現快速效能。它為流行的程式語言(例如Scala,Python,Java和R)提供了高階API。
在本快速教程中,我們將介紹Spark的三個基本概念:資料幀,資料集和RDD。
資料框DataFrame
從Spark 1.3開始,Spark SQL引入了表格形式的資料抽象,稱為DataFrame。從那時起,它已成為Spark中最重要的功能之一。當我們要處理結構化和半結構化的分散式資料時,此API很有用。
在第3節中,我們將討論彈性分散式資料集(RDD)。 DataFrame以比RDD更有效的方式儲存資料,這是因為它們使用RDD的不變,記憶體中,彈性,分散式和並行功能,但它們也將架構應用於資料。DataFrames還可以將SQL程式碼轉換為最佳化的低階RDD操作。
我們可以透過三種方式建立DataFrame:
- 轉換現有的RDD
- 執行SQL查詢
- 載入外部資料
Spark團隊在2.0版中引入了SparkSession,它統一了所有不同的上下文,從而確保開發人員無需擔心建立不同的上下文:
SparkSession session = SparkSession.builder() .appName("TouristDataFrameExample") .master("local<li>") .getOrCreate(); DataFrameReader dataFrameReader = session.read(); |
我們將分析Tourist.csv檔案:
Dataset<Row> data = dataFrameReader.option("header", "true") .csv("data/Tourist.csv"); |
由於Spark 2.0 DataFrame成為Row型別的資料集,因此我們可以將DataFrame用作Dataset <Row>的別名。
我們可以選擇感興趣的特定列。我們還可以過濾和分組給定的列:
data.select(col("country"), col("year"), col("value")) .show(); data.filter(col("country").equalTo("Mexico")) .show(); data.groupBy(col("country")) .count() .show(); |
資料集Datasets
資料集是一組強型別的結構化資料。它們提供了熟悉的物件導向程式設計風格以及型別安全性的好處,因為資料集可以在編譯時檢查語法並捕獲錯誤。
資料集是DataFrame的擴充套件,因此我們可以將DataFrame視為資料集的無型別檢視。
Spark團隊在Spark 1.6中釋出了Dataset API,正如他們提到的那樣:“ Spark Datasets的目標是提供一個API,使使用者可以輕鬆地表達物件域上的轉換,同時還提供Spark SQL執行的效能和魯棒性優勢。發動機”。
首先,我們需要建立一個TouristData型別的類:
public class TouristData { private String region; private String country; private String year; private String series; private Double value; private String footnotes; private String source; // ... getters and setters } |
要將每個記錄對映到指定的型別,我們將需要使用編碼器。編碼器在Java物件和Spark的內部二進位制格式之間進行轉換:
// SparkSession initialization and data load Dataset<Row> responseWithSelectedColumns = data.select(col("region"), col("country"), col("year"), col("series"), col("value").cast("double"), col("footnotes"), col("source")); Dataset<TouristData> typedDataset = responseWithSelectedColumns .as(Encoders.bean(TouristData.class)); |
與DataFrame一樣,我們可以按特定的列進行過濾和分組:
typedDataset.filter((FilterFunction) record -> record.getCountry() .equals("Norway")) .show(); typedDataset.groupBy(typedDataset.col("country")) .count() .show(); |
我們還可以進行操作,例如按列匹配特定範圍進行過濾或計算特定列的總和,以獲取其總值:
typedDataset.filter((FilterFunction) record -> record.getYear() != null && (Long.valueOf(record.getYear()) > 2010 && Long.valueOf(record.getYear()) < 2017)).show(); typedDataset.filter((FilterFunction) record -> record.getValue() != null && record.getSeries() .contains("expenditure")) .groupBy("country") .agg(sum("value")) .show(); |
RDD
彈性分散式資料集或RDD是Spark的主要程式設計抽象。它代表了不可變,有彈性和分散式的元素的集合。
一個RDD封裝了一個大型資料集,Spark將自動在整個叢集中分佈RDD中包含的資料,並並行化我們對其執行的操作。
我們只能透過穩定儲存中的資料操作或其他RDD上的操作來建立RDD。
當我們處理大量資料並且資料分佈在群集計算機上時,容錯能力至關重要。RDD由於Spark內建的故障恢復機制而具有彈性。Spark依賴於以下事實:RDD會記住它們的建立方式,以便我們可以輕鬆地追溯沿襲來恢復分割槽。
我們可以對RDD執行兩種型別的操作:Transformations和Actions。
- 轉變
我們可以將轉換應用於RDD以操縱其資料。執行完此操作後,我們將得到一個全新的RDD,因為RDD是不可變的物件。
我們將檢查如何實現Map和Filter,這是兩種最常見的轉換。
首先,我們需要建立一個JavaSparkContext並從Tourist.csv檔案中將資料作為RDD載入:
SparkConf conf = new SparkConf().setAppName("uppercaseCountries") .setMaster("local<li>"); JavaSparkContext sc = new JavaSparkContext(conf); JavaRDD<String> tourists = sc.textFile("data/Tourist.csv"); |
接下來,讓我們應用map函式從每個記錄中獲取國家的名稱,並將名稱轉換為大寫。我們可以將此新生成的資料集儲存為磁碟上的文字檔案:
JavaRDD<String> upperCaseCountries = tourists.map(line -> { String[] columns = line.split(COMMA_DELIMITER); return columns[1].toUpperCase(); }).distinct(); upperCaseCountries.saveAsTextFile("data/output/uppercase.txt"); |
如果只想選擇一個特定國家/地區,則可以對原始遊客RDD應用過濾功能:
JavaRDD<String> touristsInMexico = tourists .filter(line -> line.split(COMMA_DELIMITER)[1].equals("Mexico")); touristsInMexico.saveAsTextFile("data/output/touristInMexico.txt"); |
- Action
在對資料進行一些計算之後,動作將返回最終值或將結果儲存到磁碟。
Spark中經常使用的兩個動作是Count和Reduce。
讓我們在CSV檔案中計算國家總數:
// Spark Context initialization and data load JavaRDD<String> countries = tourists.map(line -> { String[] columns = line.split(COMMA_DELIMITER); return columns[1]; }).distinct(); Long numberOfCountries = countries.count(); |
現在,我們將按國家/地區計算總支出。我們需要過濾描述中包含支出的記錄。
代替使用JavaRDD,我們將使用JavaPairRDD。一對RDD是一種RDD,可以儲存鍵值對。接下來讓我們檢查一下:
JavaRDD<String> touristsExpenditure = tourists .filter(line -> line.split(COMMA_DELIMITER)[3].contains("expenditure")); JavaPairRDD<String, Double> expenditurePairRdd = touristsExpenditure .mapToPair(line -> { String[] columns = line.split(COMMA_DELIMITER); return new Tuple2<>(columns[1], Double.valueOf(columns[6])); }); List<Tuple2<String, Double>> totalByCountry = expenditurePairRdd .reduceByKey((x, y) -> x + y) .collect(); |
綜上所述,當我們需要特定於域的API,需要聚合,求和或SQL查詢等高階表示式時,應使用DataFrames或Datasets。或者當我們想要在編譯時進行型別安全時。
另一方面,當資料是非結構化的並且不需要實現特定的架構時,或者在需要低階的轉換和操作時,我們應該使用RDD。
與往常一樣,所有程式碼示例都可以在GitHub上獲得。
相關文章
- BI、資料倉儲和資料分析之間的區別
- 【大資料】Spark RDD基礎大資料Spark
- 大資料學習—Spark核心概念RDD大資料Spark
- Apache Kafka資料模型概念簡介 - BaeldungApacheKafka模型
- 使用Apache Spark和Apache Hudi構建分析資料湖ApacheSpark
- 深入原始碼理解Spark RDD的資料分割槽原理原始碼Spark
- SpringBoot的repackage和Maven打包命令之間的區別 - BaeldungSpring BootPackageMaven
- 大資料分散式計算系統 Spark 入門核心之 RDD大資料分散式Spark
- spark: RDD與DataFrame之間的相互轉換Spark
- 【clickhouse專欄】資料庫、資料倉儲之間的區別與聯絡資料庫
- JdbcTemplate查詢資料 三種callback之間的區別JDBC
- 區別值型別資料和引用型別資料型別
- python不同資料型別之間的區別有什麼?Python資料型別
- 不同字符集資料庫之間的資料同步問題:資料庫
- RDD、DataFrame和DataSet的區別
- js資料型別之基本資料型別和引用資料型別JS資料型別
- 大資料分析與機器學習之間的區別與聯絡大資料機器學習
- 快取Apache Spark RDD - 效能調優快取ApacheSpark
- 資料倉儲和傳統資料庫的區別資料庫
- PyTorch資料和NumPy資料之間的互操作PyTorch
- SQL資料型別和C#資料型別間的轉換SQL資料型別C#
- 在Apache Hadoop和Spark上加速大資料加密 [session]ApacheHadoopSpark大資料加密Session
- 使用R和Apache Spark處理大規模資料 [session]ApacheSparkSession
- 不同字符集資料庫之間的資料同步問題-補資料庫
- 資料型別和字符集資料型別
- 大資料Spark叢集模式配置大資料Spark模式
- 資料庫和資料倉儲的區別在哪兒?CN資料庫
- Java 資料型別之間的轉換Java資料型別
- 雲端計算、大資料和物聯網之間,之間有什麼關係與區別?大資料
- 大資料與海量資料的區別大資料
- “大資料”與“海量資料”的區別大資料
- 資料結構之資料、資料元素、資料項、資料物件之間的關係資料結構物件
- 在不同字符集的資料庫之間匯入資料的方法(轉)資料庫
- 資料庫中odbc和jdbc的區別-------java資料庫學習筆記之1資料庫JDBCJava筆記
- 大資料架構之:Spark大資料架構Spark
- NSData之間資料型別轉化資料型別
- 奈學:資料湖和資料倉儲的區別有哪些?
- 淺談大資料、資料分析、資料探勘的區別!大資料