Spark 2.2.1 + Hive 案例之不使用现有的Hive环境;使用现有的Hive数据仓库;UDF自定义函数

Spark 2.2.1 + Hive 案例之不使用现有的Hive环境;使用现有的Hive数据仓库;UDF自定义函数  

Spark SQL支持读写存储在Apache Hive中的数据。Spark 2.2.1中,不需要显式地创建SparkContextSQLContextHiveContext实例,其已经封装在SparkSession中。 Spark 2.2.1中的 SparkSession对于 Hive 的各个特性提供了内置支持,包括使用 HiveQL 编写查询语句,使用 Hive UDFs 以及从 Hive 表中读取数据。

Spark SQL 支持从 Hive 中读取数据以及保存数据到Hive中。第三方框架Hive 有大量依赖包,默认部署的 Spark 不包含这些依赖包,需将Hive 的依赖包添加到Spark ClasspathSpark 将自动加载这些依赖包。注意,Hive的依赖包也必须分发到各个节点,因为需要通过Hive序列化和反序列化库来读取Hive数据和将数据写入 Hive

Spark 2.2.1使用HiveQL语句的两种情况:

1)      已经部署Hive环境,Spark Hive协作。Spark需要实例化支持Hive

SparkSession。将配置文件hive-site.xml, core-site.xml (如果有安全相关配置) 以及 hdfs-site.xml拷贝到 $SPARK_HOME/conf 目录下。

2)      如果没有现成部署好的HiveSpark仍可启用 Hive 支持。当没有使用

hive-site.xml 进行配置时,Spark会自动的在当前目录创建 metastore_db 并在 spark.sql.warehouse.dir 指定的目录创建一个目录,用作 spark-warehouse 目录。注意:hive-site.xml 中的hive.metastore.warehouse.dirSpark 2.0.0 取而代之,使用 spark.sql.warehouse.dir 来指定 warehouse 数据库的默认目录。另外,需要赋予启动Application用户对这个目录的写权限。

 

下面给出两种情况下使用HiveQL语句的示例。

(一)不使用现有的Hive环境

1)      如果没有现成部署好的Hive环境,Spark 2.2.1默认也可启用HiveQL支持。

默认在当前用户/root下建立元数据数据库metastore_db及数据仓库存储目录spark-warehouse

root@master:~/metastore_db/log#cd /root/

root@master:~# ls/root  |grep metastore_db

metastore_db

root@master:~# ls/root  |grep spark

spark-warehouse

 

SparkSession使用spark.catalog实例访问Spark系统的Catalog元数据,例如:查询Spark当前所有的数据库。默认数据库是default,描述为默认的Hive数据库(Default Hive database),本地数据库文件地址是(file:/root/spark-warehouse)。

scala>spark.catalog.listDatabases.show(false)

+-------+---------------------+--------------------------+

|name   |description          |locationUri               |

+-------+---------------------+--------------------------+

|default|DefaultHive database|file:/root/spark-warehouse|

+-------+---------------------+--------------------------+

 

查询Spark当前所有数据库中所有的表。

scala>spark.catalog.listTables.show(false) 

18/02/18 20:21:56INFO parser.CatalystSqlParser: Parsing command: array

18/02/18 20:21:56INFO parser.CatalystSqlParser: Parsing command: bigint

18/02/18 20:21:56INFO parser.CatalystSqlParser: Parsing command: string

+-------------+--------+-----------+---------+-----------+

|name        |database|description|tableType|isTemporary|

+-------------+--------+-----------+---------+-----------+

|people_table|default |null       |MANAGED  |false     |

|people_table2|default|null       |MANAGED  |false     |

|parquetfile  |null   |null       |TEMPORARY|true       |

|people       |null   |null       |TEMPORARY|true       |

+-------------+--------+-----------+---------+-----------+

 

2)      构建数据库表(表的名称为src)。

        通过spark.sql("CREATE TABLE IF NOT EXISTS src (keyINT, value STRING)")的HiveQL的建表语句,构建了一个名为src的数据库表,包含key和value两列。

scala>spark.sql("CREATE TABLE IF NOT EXISTS src (key INT, value STRING)")

18/02/18 20:37:49INFO spark.ContextCleaner: Cleaned accumulator 736

18/02/18 20:45:02INFO execution.SparkSqlParser: Parsing command: CREATE TABLE IF NOT EXISTS src(key INT, value STRING)

18/02/18 20:45:07WARN metastore.HiveMetaStore: Location: file:/root/spark-warehouse/srcspecified for non-external table:src

res56:org.apache.spark.sql.DataFrame = []

 

Spark的默认数据库是default,默认的Hive数据库的本地数据库文件目录是(file:/root/spark-warehouse),查询src表已经在spark-warehouse目录下构建成功。

root@master:~/spark-warehouse#ls -ltr

total 12

drwxr-xr-x 2 rootroot 4096 Feb 17 20:13 people_table

drwxr-xr-x 2 rootroot 4096 Feb 17 20:34 people_table2

drwxr-xr-x 2 rootroot 4096 Feb 18 20:45 src

 

3)       加载本地文件到表(src)中。

通过HiveQL的Load语句:"LOAD DATA LOCAL INPATH ' /usr/local/spark-2.2.1-bin-hadoop2.6/examples/src/main/resources/kv1.txt' INTO TABLE src",将本地文件系统中的kv1.txt文件加载到src表中。该文件位于Spark部署目录下。

kv1.txt文件的格式(Key-Value)包括2列,第一列Key是随机数字,第二列Value是将一列的数字加上“val_”前缀。kv1.txt文件的部分记录如下。

238 val_238

86 val_86

311 val_311

27 val_27

165 val_165

409 val_409

……

 

使用HiveQL的Load语句加载kv1.txt文件。

scala>spark.sql("LOAD DATA LOCAL INPATH '/usr/local/spark-2.2.1-bin-

hadoop2.6/examples/src/main/resources/kv1.txt'INTO TABLE src")

18/02/18 21:22:02INFO execution.SparkSqlParser: Parsing command: LOAD DATA LOCAL INPATH'/usr/local/spark-2.2.1-bin-hadoop2.6/examples/src/main/resources/kv1.txt' INTOTABLE src

18/02/18 21:22:02INFO parser.CatalystSqlParser: Parsing command: int

18/02/18 21:22:02INFO parser.CatalystSqlParser: Parsing command: string

res61:org.apache.spark.sql.DataFrame = []

        

4)       查询src表。

scala>spark.sql("SELECT key, value FROM src ")

18/02/18 21:24:20INFO execution.SparkSqlParser: Parsing command: SELECT key, value FROM src

18/02/18 21:24:20INFO parser.CatalystSqlParser: Parsing command: int

18/02/18 21:24:20INFO parser.CatalystSqlParser: Parsing command: string

res62:org.apache.spark.sql.DataFrame = [key: int, value: string]

通过HiveQL的查询语句:" SELECT key, value FROMsrc ",从src表中查询指定的key和value两列数据来构建出DataFrame实例。

 

5)       在界面输出src表的查询结果。

scala>spark.sql("SELECT key, value FROM src ").collect().foreach(println)

18/02/18 21:26:11INFO execution.SparkSqlParser: Parsing command: SELECT key, value FROM src

18/02/18 21:26:11INFO parser.CatalystSqlParser: Parsing command: int

18/02/18 21:26:11INFO parser.CatalystSqlParser: Parsing command: string

18/02/18 21:26:12INFO codegen.CodeGenerator: Code generated in 16.122687 ms

…….

18/02/18 21:26:14INFO rdd.HadoopRDD: Input split: file:/root/spark-warehouse/src/kv1.txt:0+5812

……

[238,val_238]

[86,val_86]

[311,val_311]

[27,val_27]

[165,val_165]

[409,val_409]

[255,val_255]

……

 

6)       删除src表。

scala>spark.sql("DROP table src")

18/02/18 21:32:36INFO execution.SparkSqlParser: Parsing command: DROP table src

18/02/18 21:32:36INFO parser.CatalystSqlParser: Parsing command: int

18/02/18 21:32:36INFO parser.CatalystSqlParser: Parsing command: string

18/02/18 21:32:36INFO parser.CatalystSqlParser: Parsing command: int

18/02/18 21:32:36INFO parser.CatalystSqlParser: Parsing command: string

18/02/18 21:32:37INFO spark.ContextCleaner: Cleaned accumulator 877

18/02/18 21:32:37INFO storage.BlockManagerInfo: Removed broadcast_42_piece0 on master:43661 inmemory (size: 4.3 KB, free: 413.9 MB)

18/02/18 21:32:37INFO storage.BlockManagerInfo: Removed broadcast_41_piece0 on master:43661 inmemory (size: 21.7 KB, free: 413.9 MB)

res64:org.apache.spark.sql.DataFrame = []

 

查询Spark的默认Hive数据库的本地数据库文件目录(file:/root/spark-warehouse),可以看到src表已经被删除。

root@master:~/spark-warehouse#ls -ltr

total 8

drwxr-xr-x 2 rootroot 4096 Feb 17 20:13 people_table

drwxr-xr-x 2 rootroot 4096 Feb 17 20:34 people_table2

oot@master:~/spark-warehouse#

 


 

(二) 使用现有的Hive数据仓库。Spark 2.2.1基于Hive进行操作。

  • Hive的操作。首先给出Hive+Mysql的操作案例,Hive以Mysql作为元数据存储数据库,在Hive中新建表操作。
  • Spark2.2.1的操作。使用Spark 2.2.1 基于Hive操作,在Spark Shell中使用Spark SQL新建表,在Hive中验证表成功建立。

 

1)       前提准备:已经安装好Mysql数据库。Mysql数据库版本检查如下。

root@master:/usr/local/apache-hive-1.2.1/conf#mysql -V

mysql  Ver 14.14 Distrib 5.5.47, fordebian-linux-gnu (x86_64) using readline 6.3

 

root@master:~#mysql -u root -p

Enter password:

Welcome to theMySQL monitor.  Commands end with ; or\g.

Your MySQL connectionid is 40

Server version:5.5.47-0ubuntu0.14.04.1 (Ubuntu)

……

 

Mysql驱动的下载地址(https://dev.mysql.com/downloads/connector/j/)。

 

2)       前提准备:已经安装好Hive环境,当前Hive环境使用Mysql作为默认的元数据数据库。

  • 已将mysql-connector-java-5.1.35-bin.jar拷贝到/usr/local/apache-hive-1.2.1/lib目录下。
  • 已Hive的Jar包替换Hadoop较低版本的相同Jar包:用/usr/local/apache-hive-1.2.1/lib/jline-2.12.jar替换/usr/local/hadoop-2.6.0/share/hadoop/yarn/lib/jline-0.9.94.jar;如果没有替换,运行./bin/hive时会报jline的类不兼容。
root@master:/usr/local/hadoop-2.6.0/share/hadoop/yarn/lib#ls  | grep jline-2.12.jar

jline-2.12.jar

 

3)    Linux统/etc/profile文件中配置Hadoop、Hive环境变量,或者在hive-env.sh配置文件中配置。

root@master:~#cat /etc/profile

……

exportHADOOP_HOME=/usr/local/hadoop-2.6.0

exportHIVE_HOME=/usr/local/apache-hive-1.2.1

exportPATH=.:$PATH:$JAVA_HOME/bin:$SCALA_HOME/bin:$HADOOP_HOME/bin:$SPARK_HOME/bin:$HIVE_HOME/bin

……

 

4)       Hive的hive-site.xml配置示例。







         

          javax.jdo.option.ConnectionURL

          jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true

          JDBC connect string for a JDBCmetastore

         

 

         

          javax.jdo.option.ConnectionDriverName

          com.mysql.jdbc.Driver

          Driver class name for a JDBCmetastore

         

 

         

          javax.jdo.option.ConnectionUserName

          root

          username to use against metastoredatabase

         

 

         

          javax.jdo.option.ConnectionPassword

          root

          password to use against metastoredatabase

         

 

         

          hive.metastore.schema.verification

          false

         

        

         

          hive.metastore.warehouse.dir

          /user/hive/warehouse

         

 



 

其中,javax.jdo.option.ConnectionURL为Mysql数据库连接的URL信息,这里连接到localhost(192.168.189.1)的数据库Hive (已在Mysql中里面建立数据库,其名称设置为Hive),如果在Mysql中的Hive数据库不存在,将自动新建一个数据库(名称设置为Hive)。javax.jdo.option.ConnectionUserName、javax.jdo.option.ConnectionPassword分别设置用户名、密码信息。hive.metastore.warehouse.dir是Hive数据在HDFS中的存储位置。

使用Mysql作为Hive MetaStore元数据的存储数据库,Mysql中和Hive的相关表,如表3-2所示。

表名

说明

关联键

TBLS

所有hive表的基本信息(表名,创建时间,所属者等)

TBL_ID,SD_ID

TABLE_PARAMS

表级属性,(如是否外部表,表注释,最后修改时间等)

TBL_ID

COLUMNS_V2

Hive表字段信息(字段注释,字段名,字段类型,字段序号)

SD_ID

SDS

所有hive表、表分区所对应的HDFS数据目录和数据格式

SD_ID,SERDE_ID

SERDE_PARAMS

序列化反序列化信息,如行分隔符、列分隔符、NULL的表示字符等

SERDE_ID

PARTITIONS

Hive表分区信息(所属表,分区值)

PART_ID,SD_ID,TBL_ID

PARTITION_KEYS

Hive分区表分区键(即分区字段)

TBL_ID

PARTITION_KEY_VALS

Hive表分区名(键值)

PART_ID

表 3 - 2 Mysql作为Hive MetaStore元数据的相关表

 本节案例是实践Spark SQL,因此对Hive的环境配置只给出最基本的配置。如果需要修改,可以参考Hive官网的部署(http://hive.apache.org/)。例如:

  •  Hive数据库的编码配置: javax.jdo.option.ConnectionURL中添加&characterEncoding=latin1。其中ConnectionURL参数中的&符号在XML文件中需转义。
  • Metastore的远程访问的配置:hive.metastore.uris设置Value值为thrift://master:9083等等。

 

 

5)       在Hive中操作新建表。

查询Hive中已有的数据库。

hive> showdatabases;

OK

default

hive

hivestudy

Time taken: 2.305seconds, Fetched: 3 row(s)

 

Hive中已经建立了hive、hivestudy数据库及Hive的默认数据库default,这里使用hive数据库。

hive> use hive;

OK

Time taken: 0.12seconds

 

在Hive的数据库(hive)中新建pokes表。

hive> showtables;

OK

Time taken: 0.03seconds

hive>  CREATE TABLE pokes (foo INT, bar STRING);

OK

Time taken: 1.481seconds

hive> showtables;

OK

pokes

Time taken: 0.046seconds, Fetched: 1 row(s)

hive>

 

         查看Web Interface界面上HDFS的文件系统信息,如图3-6所示。

Spark 2.2.1 + Hive 案例之不使用现有的Hive环境;使用现有的Hive数据仓库;UDF自定义函数_第1张图片

3 - 6Hadoop文件系统在HiveCLI中构建表之后的界面

在HDFS系统/user/hive/warehouse/hive.db的 hive数据库目录下,生成对应表名的目录pokes。

         在Mysql中查询Hive数据库新建立的pokes表的元数据信息。例如,Mysql数据库中TBLS表记录中包括Hive中表的基本信息(表名,创建时间,所属者等),从Mysql的TBLS表中查询新建pokes的所属者是root,表名是pokes。

mysql>  select CREATE_TIME,OWNER,TBL_NAME from  TBLS where TBL_NAME

="pokes";

+-------------+-------+----------+

| CREATE_TIME |OWNER | TBL_NAME |

+-------------+-------+----------+

|  1519009476 | root  | pokes   |

 

6)       在Spark 2.2.1中操作,查询Hive数据库的表的信息。

前提准备:将Hive的配置文件hive-site.xml拷贝到 Spark2.2.1$SPARK_HOME/conf 目录下。

root@master:/usr/local/apache-hive-1.2.1/conf#cp /usr/local/apache-hive-1.2.1/conf/hive-site.xml

/usr/local/spark-2.2.1-bin-hadoop2.6/conf/

……

root@master:/usr/local/spark-2.2.1-bin-hadoop2.6/conf#ls |grep hive-site.xml 

hive-site.xml

 

在执行Spark Shell或者Spark Submit命令的时候,需在--driver-class-path配置mysql-connector-java-5.1.35-bin.jar的路径。示例如下

 

--driver-class-path/usr/local/apache-hive-1.2.1/lib/mysql-connector-java-5.1.13-bin.jar

 

注意:如果启动Spark-Shell脚本时,没有配置--driver-class-pathmysql-connector-java-5.1.35-bin.jar包的路径,在加载类时会找不到类“com.mysql.jdbc.Driver”的路径,导致Mysql的数据库连接失败,出现以下异常提示:

scala>spark.sql("show tables").show

…….

Caused by:org.datanucleus.exceptions.NucleusException: Attempt to invoke the"BONECP" plugin

to create aConnectionPool gave an error : The specified datastore driver("com.mysql.jdbc.Driver") was not found in the CLASSPATH. Pleasecheck your CLASSPATH specification, and the name of the driver.

   at org.datanucleus.store.rdbms.ConnectionFactoryImpl.generateDataSources(ConnectionFactoryImpl.java:259)

……..

 

小技巧:

l 当日志出现Error时,跟踪其调用堆栈信息,查找关键字为Caused by,可能中一个异常堆栈信息中会出现多个Caused by,这时候最下面那个,也就是最早抛出异常的地方,往往就是错误的根源,问题的根源才是解决问题的出发点。

l 类找不到的根本原因,主要是由JVM的类加载机制导致的。如果当前执行环境(需要注意在分布式计算框架下,是对应真正执行的节点,与提交点等其他节点的环境无关)下的CLASSPATH中找不到该jar包,就会出现类找不到的异常。

l Spark计算框架已经提供了自动将所需Jar包添加到执行环境的CLASSPATH上了,如果执行环境本身没有部署该Jar包,就可以充分利用spark的--jars参数,自动设置。

 

         配置--driver-class-path参数,运行Spark Shell应用程序。

root@master:~#spark-shell  --masterspark://192.168.189.1:7077  \

>      --driver-class-path/usr/local/apache-hive-1.2.1/lib/mysql-connector-java-5.1.13-bin.jar  \

>      --executor-memory 512m  --total-executor-cores 4

Setting default loglevel to "WARN".

To adjust logginglevel use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).

18/02/19 13:43:13WARN util.NativeCodeLoader: Unable to load native-hadoop library for yourplatform... using builtin-java classes where applicable

Spark context WebUI available at http://master:4040

Spark contextavailable as 'sc' (master = spark://192.168.189.1:7077, app id =app-20180219134317-0000).

Spark sessionavailable as 'spark'.

Welcome to

      ____              __

     / __/__ ___ _____/ /__

    _\ \/ _ \/ _ `/ __/  '_/

   /___/ .__/\_,_/_/ /_/\_\   version 2.2.1

 

在Spark Shell交互式界面中,通过spark.sql("usehive")语句使用Hive中的hive数据库,查询hive数据库现有的表信息,其中可以查看到hive刚创建的pokes表。

scala> spark.sql("use hive")

18/02/19 15:32:12 WARN metastore.ObjectStore: Failed toget database global_temp, returning NoSuchObjectException

res0: org.apache.spark.sql.DataFrame = []

 

scala> spark.sql("show tables").show

+--------+---------+-----------+

|database|tableName|isTemporary|

+--------+---------+-----------+

|    hive|    pokes|     false|

+--------+---------+-----------+

 

3)       在Spark 2.2.1中操作,在Spark SQL中创建表pokes_test。

scala>spark.sql("CREATE TABLE pokes_test (foo INT, bar STRING)")

18/02/19 15:43:41WARN metastore.HiveMetaStore: Location:hdfs://master:9000/user/hive/warehouse/hive.db/pokes_test specified fornon-external table:pokes_test

res2:org.apache.spark.sql.DataFrame = []

 

登陆Hive,在Hive中查看Spark 2.2.1 SQL新建的表pokes_test。查看pokes_test表已经在Hive中建立。

hive> use hive;

OK

Time taken: 0.03seconds

hive> showtables;

OK

pokes

pokes_test

Time taken: 0.06seconds, Fetched: 2 row(s)

hive>

 

         查看Web Interface界面上HDFS的文件系统信息,如图3-7所示。

Spark 2.2.1 + Hive 案例之不使用现有的Hive环境;使用现有的Hive数据仓库;UDF自定义函数_第2张图片

图 3 - 7 pokes_test表在HDFS的文件系统信息

登陆Mysql数据库,查询Hive数据库元数据的信息。在Spark 2.2.1 SQL新建的表pokes_test,Hive已经将pokes_test的元数据同步到Mysql数据库,例如:在Mysql数据库hive的TBLS表中查询pokes_test表的建立时间、所属者、及表名。

mysql> use hive;

Reading table informationfor completion of table and column names

You can turn offthis feature to get a quicker startup with -A

 

mysql> selectCREATE_TIME,OWNER, TBL_NAME   from TBLSwhere 

TBL_NAME='pokes_test';

+-------------+-------+------------+

| CREATE_TIME |OWNER | TBL_NAME   |

+-------------+-------+------------+

|  1519026222 | root  | pokes_test |

+-------------+-------+------------+

1 row in set (0.00sec)

 

4)       在Spark Shell中查询Hive中表名信息。

scala>spark.sqlContext.tableNames

res7: Array[String]= Array(pokes, pokes_test)

 

(二) UDF扩展用户定义函数场景下的实战案例。

本节给出UDFs注册实例,基于UDF的定义,给出DataFrameSQL中的两种案例。

1)     加载数据源。

数据源使用Spark 2.2.1本身自带的本地数据源文件examples/src/main/resources/people.txt,people.txt数据源文件包括姓名、年龄两列,内容如下:

root@master:/usr/local/spark-2.2.1-bin-hadoop2.6/examples/src/main/resources#cat  people.txt

Michael, 29

Andy, 30

Justin, 19

 

将文件examples/src/main/resources/people.txt上传到HDFS文件系统中/resources。

root@master:~# hdfs dfs -put /usr/local/spark-2.2.1-bin-

hadoop2.6/examples/src/main/resources/people.txt  /resources

root@master:~# hdfsdfs -ls /resources |grep people.txt

-rw-r--r--   3 rootsupergroup         32 2018-02-19 20:52/resources/people.txt

 

定义caseclass People类,包括姓名及年龄成员变量。

scala> caseclass People(name: String, age: Int)

defined classPeople

 

加载HDFS系统中的people.txt数据源文件,每行数据按“,”切分以后,提取第0个元素姓名,第1个元素年龄放入People类中,并转换为DataFrame。然后注册为临时表people。

scala> val people

=spark.sparkContext.textFile("/resources/people.txt").map(_.split(",")).map(attributes=> People(attributes(0), attributes(1).trim.toInt)).toDF()

people: org.apache.spark.sql.DataFrame = [name: string, age: int]

 

scala> people.createOrReplaceTempView("people")

 

2)       在Spark SQL构建求字符串长度的UDF注册名为strLenScala,其使用占位符“_”将每个读入的字符串元素计算长度。

scala>spark.udf.register("strLenScala", (_: String).length)

res8: org.apache.spark.sql.expressions.UserDefinedFunction =UserDefinedFunction(,IntegerType,Some(List(StringType)))

 

3)       在Spark SQL构建对列进行格式化的UDF注册名为fmtNum。导入DecimalFormat类,将每个读入的整型元素进行格式化。

scala> importjava.text.DecimalFormat

importjava.text.DecimalFormat

 

scala> spark.udf.register("fmtNum", (d: Int) => {

     |                          val dfmt = newDecimalFormat("###.00")

     |                        dfmt.format(d.toDouble)})

res11: org.apache.spark.sql.expressions.UserDefinedFunction =UserDefinedFunction(,StringType,Some(List(IntegerType)))

 

注册的strLenScala的函数功能为将传入的字符串转换为字符串的长度,fmtNum对Int的age进行格式化。

 

4)       在Spark 2.2.1 SQL中的使用UDF案例如下。在SQL语句的WHERE条件表达式中调用strLenScala的UDF函数,计算姓名列的长度。查询姓名长度小于等于13,以及年龄小于32岁的人员信息。

scala> val udfRslt = spark.sql("SELECT name, age FROM peopleWHERE strLenScala(name) <=

13 AND age <= 32").show

+-------+---+

|   name|age|

+-------+---+

|Michael| 29|

|   Andy| 30|

| Justin| 19|

+-------+---+

 

udfRslt: Unit = ()

 

5)       在Spark 2.2.1 DataFrame中的UDF使用案例如下。使用selectExpr调用strLenScala的UDF函数显示姓名长度、年龄的人员信息。

scala>people.selectExpr("strLenScala(name)","age").toDF("nameLen","age").show

+-------+---+

|nameLen|age|

+-------+---+

|      7| 29|

|      4| 30|

|      6| 19|

+-------+---+

 

scala>people.selectExpr("strLenScala(name) as nameLen","age").show

+-------+---+

|nameLen|age|

+-------+---+

|      7| 29|

|      4| 30|

|      6| 19|

+-------+---+

 

         使用注册的UDF函数strLenScala,返回的DataFrame的Schemma会自动进行推导。

scala>people.selectExpr("strLenScala(name) as nameLen","age").printSchema

root

 |-- nameLen: integer (nullable = true)

 |-- age: integer (nullable = false)

 

         使用selectExpr分别调用strLenScalafmtNumUDF函数查询姓名长度、年龄格式化的人员信息。

scala>people.selectExpr("strLenScala(name) as nameLen","fmtNum(age)").show

+-------+---------------+

|nameLen|UDF:fmtNum(age)|

+-------+---------------+

|      7|          29.00|

|      4|          30.00|

|      6|          19.00|

+-------+---------------+

 

         使用注册的UDF的fmtNum后,返回的DataFrame的Schemma也会自动进行推导,Age字段自动推导为String类型。

scala>people.selectExpr("strLenScala(name) as nameLen","fmtNum(age)").printSchema

root

 |-- nameLen: integer (nullable = true)

 |-- UDF:fmtNum(age): string (nullable = true)

 


2018年新春报喜!热烈祝贺王家林大咖大数据经典传奇著作《SPARK大数据商业实战三部曲》畅销书籍 清华大学出版社发行上市!

本书基于Spark 2.2.0最新版本(2017年7月11日发布),以Spark商业案例实战和Spark在生产环境下几乎所有类型的性能调优为核心,以Spark内核解密为基石,分为上篇、中篇、下篇,对企业生产环境下的Spark商业案例与性能调优抽丝剥茧地进行剖析。上篇基于Spark源码,从一个动手实战案例入手,循序渐进地全面解析了Spark 2.2新特性及Spark内核源码;中篇选取Spark开发中最具有代表的经典学习案例,深入浅出地介绍,在案例中综合应用Spark的大数据技术;下篇性能调优内容基本完全覆盖了Spark在生产环境下的所有调优技术。


本书适合所有Spark学习者和从业人员使用。对于有分布式计算框架应用经验的人员,本书也可以作为Spark高手修炼的参考书籍。同时,本书也特别适合作为高等院校的大数据教材使用。

当当网、京东、淘宝、亚马逊等网店已可购买!欢迎大家购买学习!

当当网址: http://product.dangdang.com/25230552.html

你可能感兴趣的:(AI,&,Big,Data案例实战课程)