Spark SQL中對Json支援的詳細介紹
在這篇文章中,我將介紹一下Spark SQL對Json的支援,這個特性是Databricks的開發者們的努力結果,它的目的就是在Spark中使得查詢和建立JSON資料變得非常地簡單。隨著WEB和手機應用的流行,JSON格式的資料已經是WEB Service API之間通訊以及資料的長期儲存的事實上的標準格式了。但是使用現有的工具,使用者常常需要開發出複雜的程式來讀寫分析系統中的JSON資料集。而Spark SQL中對JSON資料的支援極大地簡化了使用JSON資料的終端的相關工作,Spark SQL對JSON資料的支援是從1.1版本開始釋出,並且在Spark 1.2版本中進行了加強。
現有Json工具實踐
在實踐中,使用者往往在處理現代分析系統中JSON格式的資料中遇到各種各樣的困難。如果使用者需要將資料集寫成JSON格式的話,他們需要編寫複雜的邏輯程式來轉換他們的資料集到JSON格式中。如果需要讀取或者查詢JSON資料集,他們通常需要預先定義好資料結構並用它來轉換JSON資料。在這種情況下,使用者必須等待這些資料處理完成之後,才能夠使用他們生成的JSON資料。無論是在寫或者是讀,預先定義和維護這些模式往往使得ETL工作變得非常地繁重!並且可能消除掉JSON這種半結構化(semi-structured)的資料格式的好處。如果使用者想消費新的資料,他們不得不在建立外部表的時候定義好相關的模式,並使用自定義的JSON serialization/deserialization依賴庫,或者是在查詢JSON資料的時候使用UDF函式。
作為一個例子,如果有下面的一些JSON資料模式
{"name":"Yin", "address":{"city":"Columbus","state":"Ohio"}} {"name":"Michael", "address":{"city":null, "state":"California"}}
在類似於Hive的系統中,這些JSON物件往往作為一個值儲存到單個的列中,如果需要訪問這個資料,我們需要使用UDF來抽取出我們需要的資料。在下面的SQL查詢例子中,外層的欄位(name和address)被抽取出來,巢狀在內層的address欄位也被進一步的抽取出來:
/** * User: 過往記憶 * Date: 15-02-04 * Time: 上午07:30 * bolg: http://www.iteblog.com * 本文地址:http://www.iteblog.com/archives/1260 * 過往記憶部落格,專注於hadoop、hive、spark、shark、flume的技術部落格,大量的乾貨 * 過往記憶部落格微信公共帳號:iteblog_hadoop */ SELECT v1.name, v2.city, v2.state FROM people LATERAL VIEW json_tuple(people.jsonObject, 'name', 'address') v1 as name, address LATERAL VIEW json_tuple(v1.address, 'city', 'state') v2 as city, state;
Spark SQL中對JSON的支援
Spark SQL提供了內建的語法來查詢這些JSON資料,並且在讀寫過程中自動地推斷出JSON資料的模式。Spark SQL可以解析出JSON資料中巢狀的欄位,並且允許使用者直接訪問這些欄位,而不需要任何顯示的轉換操作。上面的查詢語句如果使用Spark SQL的話,可以這樣來寫:
SELECT name, age, address.city, address.state FROM people
在Spark SQL中載入和儲存JSON資料集
為了能夠在Spark SQL中查詢到JSON資料集,唯一需要注意的地方就是指定這些JSON資料儲存的位置。這些資料集的模式是直接可以推斷出來,並且內建就有相關的語法支援,不需要使用者顯示的定義。在程式設計中使用API中,我們可以使用SQLContext提供的jsonFile和jsonRDD方法。使用這兩個方法,我們可以利用提供的JSON資料集來建立SchemaRDD 物件。並且你可以將SchemaRDD 註冊成表。下面是一個很好的例子:
/** * User: 過往記憶 * Date: 15-02-04 * Time: 上午07:30 * bolg: http://www.iteblog.com * 本文地址:http://www.iteblog.com/archives/1260 * 過往記憶部落格,專注於hadoop、hive、spark、shark、flume的技術部落格,大量的乾貨 * 過往記憶部落格微信公共帳號:iteblog_hadoop */ // Create a SQLContext (sc is an existing SparkContext) val sqlContext = new org.apache.spark.sql.SQLContext(sc) // Suppose that you have a text file called people with the following content: // {"name":"Yin", "address":{"city":"Columbus","state":"Ohio"}} // {"name":"Michael", "address":{"city":null, "state":"California"}} // Create a SchemaRDD for the JSON dataset. val people = sqlContext.jsonFile("[the path to file people]") // Register the created SchemaRDD as a temporary table. people.registerTempTable("people")
當然,我們也可以使用純的SQL語句來建立JSON資料集。例如
CREATE TEMPORARY TABLE people USING org.apache.spark.sql.json OPTIONS (path '[the path to the JSON dataset]')
在上面的例子中,因為我們沒有顯示地定義模式,Spark SQL能夠自動地掃描這些JSON資料集,從而推斷出相關的模式。如果一個欄位是JSON物件或者陣列,Spark SQL將使用STRUCT 型別或者ARRAY型別來代表這些欄位。即使JSON數是半結構化的資料,並且不同的元素肯恩好擁有不同的模式,但是Spark SQL仍然可以解決這些問題。如果你想知道JSON資料集的模式,你可以通過使用返回來的SchemaRDD 物件中提供的printSchema()函式來列印出相應的模式,或者你也可以在SQL中使用DESCRIBE [table name]
。例如上面的people資料集的模式可以通過people.printSchema()
列印出:
root |-- address: struct (nullable = true) | |-- city: string (nullable = true) | |-- state: string (nullable = true) |-- name: string (nullable = true)
當然,使用者在利用 jsonFile 或 jsonRDD建立表的時候也可以顯示的指定一個模式到JSON資料集中。在這種情況下,Spark SQL將把這個模式和JSON資料集進行繫結,並且將不再會去推測它的模式。使用者不需要了解JSON資料集中所有的欄位。指定的模式可以是固定資料集的一個子集,也可以包含JSON資料集中不存在的欄位。
當使用者建立好代表JSON資料集的表時,使用者可以很簡單地利用SQL來對這個JSON資料集進行查詢,就像你查詢普通的表一樣。在Spark SQL中所有的查詢,查詢的返回值是SchemaRDD物件。例如:
val nameAndAddress = sqlContext.sql("SELECT name, address.city, address.state FROM people") nameAndAddress.collect.foreach(println)
查詢的結果可以直接使用,或者是被其他的分析任務使用,比如機器學習。當然,JSON資料集可以通過Spark SQL內建的記憶體列式儲存格式進行儲存,也可以儲存成其他格式,比如Parquet或者 Avro。
將SchemaRDD物件儲存成JSON檔案
在Spark SQL中,SchemaRDDs可以通過toJSON 方法儲存成JSON格式的檔案。因為SchemaRDD中已經包含了相應的模式,所以Spark SQL可以自動地將該資料集轉換成JSON,而不需要使用者顯示地指定。當然,SchemaRDDs可以通過很多其他格式的資料來源進行建立,比如Hive tables、 Parquet檔案、 JDBC、Avro檔案以及其他SchemaRDD的結果。這就意味著使用者可以很方便地將資料寫成JSON格式,而不需要考慮到源資料集的來源。
相關文章
- json詳細介紹(for Java)JSONJava
- js中typeof用法詳細介紹JS
- Android中Context的詳細介紹AndroidContext
- nGrinder詳細介紹及效能工具對比
- javascript this詳細介紹JavaScript
- JDBC 詳細介紹JDBC
- Kafka詳細介紹Kafka
- Git詳細介紹Git
- CentOS中rpm命令詳細介紹CentOS
- Http協議中Cookie詳細介紹HTTP協議Cookie
- Http Module 的詳細介紹HTTP
- asmcmd工具的詳細介紹ASM
- Mysqldump工具的詳細介紹MySql
- Go Channel 詳細介紹Go
- Nacos 介面詳細介紹
- MQ詳細命令介紹MQ
- Recovery命令詳細介紹
- Vmstat 命令詳細介紹
- 詳細介紹Java中的堆、棧和常量池Java
- Apache (http server)的詳細介紹ApacheHTTPServer
- Go中的有限狀態機FSM的詳細介紹Go
- PHP 的Closure的bind 詳細介紹PHP
- Spark介紹Spark
- 跳脫字元在前端開發中的詳細介紹字元前端
- MySQL5.6中的常用函式詳細用法介紹MySql函式
- thinkPHP模板中的語法知識詳細介紹(十二)PHP
- Flutter系列(一)——詳細介紹Flutter
- Nginx服務詳細介紹Nginx
- python字典詳細介紹Python
- Spring bean詳細介紹SpringBean
- Java異常詳細介紹Java
- 【SCN】Oracle SCN 詳細介紹Oracle
- SOLIDWORKS API詳細介紹SolidAPI
- Webpack 打包 Javascript 詳細介紹WebJavaScript
- mysql binlog詳細介紹MySql
- java泛型詳細介紹Java泛型
- 【工具】Sublime使用詳細介紹
- rman超詳細命令介紹