Spark SQL使用时需要有若干“表”的存在,这些“表”可以来自于Hive,也可以来自“临时表”。如果“表”来自于Hive,它的模式(列名、列类型等)在创建时已经确定,一般情况下我们直接通过Spark SQL分析表中的数据即可;如果“表”来自“临时表”,我们就需要考虑两个问题:

(1)“临时表”的数据是哪来的?

(2)“临时表”的模式是什么?

通过Spark的官方文档可以了解到,生成一张“临时表”需要两个要素:

(1)关联着数据的RDD;

(2)数据模式;

也就是说,我们需要将数据模式应用于关联着数据的RDD,然后就可以将该RDD注册为一张“临时表”。在这个过程中,最为重要的就是数据(模式)的数据类型,它直接影响着Spark SQL计算过程以及计算结果的正确性。

目前pyspark.sql.types支持的数据类型:NullType、StringType、BinaryType、BooleanType、DateType、TimestampType、DecimalType、DoubleType、FloatType、ByteType、IntegerType、LongType、ShortType、ArrayType、MapType、StructType(StructField),其中ArrayType、MapType、StructType我们称之为“复合类型”,其余称之为“基本类型”,“复合类型”在是“基本类型”的基础上构建而来的。

这些“基本类型”与Python数据类型的对应关系如下:

NullType

None

StringType

basestring

BinaryType

bytearray

BooleanType

bool

DateType

datetime.date

TimestampType

datetime.datetime

DecimalType

decimal.Decimal

DoubleType

float(double precision floats)

FloatType

float(single precision floats)

ByteType

int(a signed integer)

IntegerType

int(a signed 32-bit integer)

LongType

long(a signed 64-bit integer)

ShortType

int(a signed 16-bit integer)

下面我们分别介绍这几种数据类型在Spark SQL中的使用。

1. 数字类型(ByteType、ShortType、IntegerType、LongType、FloatType、DoubleType、DecimalType)

数字类型可分为两类,整数类型:ByteType、ShortType、IntegerType、LongType,使用时需要注意各自的整数表示范围;浮点类型:FloatType、DoubleType、DecimalType,使用时不但需要注意各自的浮点数表示范围,还需要注意各自的精度范围。

我们以常见的数据类型IntegerType来说明数字类型的使用方法:

a. 模拟“一行两列”的数据,并通过parallelize方法将其转换为一个RDD source,这个RDD就是关联着数据的RDD;

b. 创建数据模式,需要分别为这两列指定列名、列类型、可否包含空(Null)值;其中模式需要使用StructType表示,每一列的各个属性(列名称、列类型、可否包含空(Null)值)需要使用StructField表示;第一列的列名为col1,列类型为IntegerType,不可包含空(Null)值(False);第二列的列名为col2,列类型为IntegerType,不可包含空(Null)值(False);(注意:实际使用中每列的数据类型并不一定相同)

c. 通过applySchema方法将数据模式schema应用于RDD source,这会产生一个SchemaRDD(具有模式的RDD) table;

d. 将SchemaRDD table注册为一张表:temp_table;

到此我们就完成了创建RDD、创建Schema、注册Table的整个过程,接下来就可以使用这张表(temp_table)通过Spark(Hive) SQL完成分析。其它数字类型的使用方式类似。

实际上本例中“一行两列”的数据实际就是IntergerType的表示范围:[-2147483648, 2147483647],其它数字类型的表示范围如下:

ByteType

[-128, 127]

ShortType

[-32768, 32767]

IntegerType

[-2147483648, 2147483647]

LongType

[-9223372036854775808, 9223372036854775807]

FloatType

[1.4E-45, 3.4028235E38]

DoubleType

[4.9E-324, 1.7976931348623157E308]

可以看出,虽然我们使用Python编写程序,这些数据类型的表示范围与Java中的Byte、Short、Integer、Long、Float、Double是一致的,因为Spark是Scala实现的,而Scala运行于Java虚拟机之上,因此Spark SQL中的数据类型ByteType、ShortType、IntegerType、LongType、FloatType、DoubleType、DecimalType在运行过程中对应的数据实际上是由Java中的Byte、Short、Integer、Long、Float、Double表示的。

在使用Python编写Spark Application时需要牢记:为分析的数据选择合适的数据类型,避免因为数据溢出导致输入数据异常,但这仅仅能够解决数据输入的溢出问题,还不能解决数据在计算过程中可能出现的溢出问题。

我们将上述例子中的示例数据修改为(9223372036854775807, 9223372036854775807),数据类型修改为LongType,现在的示例数据实际是LongType所能表示的最大值,如果我们将这两例值相加,是否会出现溢出的情况呢?

输出结果:

可以看出,实际计算结果与我们预想的完全一样,这是因为col1与col2的类型为LongType,那么col1 + col2的类型也应为LongType(原因见后),然而col1 + col2的结果值18446744073709551614已经超过LongType所能表示的范围([-9223372036854775808, 9223372036854775807]),必然导致溢出。

因为我们使用的是HiveContext(SQLContext目前不被推荐使用),很多时候我们会想到使用“bigint”,

输出结果依然是:

要解释这个原因,需要了解一下Hive中数字类型各自的表示范围:

通过比对可以发现Hive BIGINT的表示范围与LongType是一致的,毕竟Hive是Java实现的,因此我们可以猜想Hive tinyint、smallint、int、bigint、float、double与Java Byte、Short、Integer、Long、Float、Double是一一对应的(仅仅是猜想,并没有实际查看源码验证),所以我们将LongType的数据类型转换为BIGINT的方式是行不通的,它们的数值范围是一样的。

那么我们应该如何解决溢出问题呢?注意到Hive Numeric Types中的最后一个数字类型:DECIMAL,从Hive 0.11.0引入,Hive 0.13.0开始支持用户可以自定义“precision”和“scale”。Decimal基于Java BigDecimal实现,可以表示不可变的任务精度的十进制数字,支持常规的数学运算(+,-,*,/)和UDF(floor、ceil、round等),也可以与其它数字类型相互转换(cast)。使用示例如下:

使用Decimal时需要注意“precision”和“scale”值的选取,Java BigDecimal(BigInteger,后续会提到)取值范围理论上取决于(虚拟)内存的大小,可见它们是比较消耗内存资源的,因此我们需要根据我们的实际需要为它们选取合适的值,并且需要满足下述条件:

整数部分位数(precision - scale) + 小数部分位数(scale) = precision

LongType所能表示的最大位数:19,因为在我们的示例中会导致溢出问题,因此我们将数值转换为Decimal,并指定precision为38,scale为0,这样我们便可以得到正确的结果:

需要注意的是计算结果类型也变成decimal.Decimal(Python),使用Python编写Spark Application时,pyspark也提供了DecimalType,它是一种比较特殊的数据类型,它不是Python内建的数据类型,使用时需要导入模块decimal,使用方式如下:

使用数据类型DecimalType时有两个地方需要注意:

(1)创建RDD时需要使用模块decimal中的Decimal生成数据;

(2)DecimalType在Spark 1.2.0环境下使用时会出现异常:java.lang.ClassCastException: java.math.BigDecimal cannot be cast to org.apache.spark.sql.catalyst.types.decimal.Decimal,在Spark 1.5.0环境下可以正常使用,但需要将模块名称由“pyspark.sql”修改为“pyspark.sql.types”。

我们明确指定数据的类型是什么,那么什么决定我们常规数学运算(+,-,*,/)之后的结果类型呢?这些数学运行在Hive中实际都是由UDF实现的(org.apache.hadoop.hive.ql.exec.FunctionRegistry),

(1)+

(2)-

(3)*

(4)/

(5)%

可以看出,“+”,“-”,“*”,“%”通过重载支持的数据类型:byte、short、int、long、float、double、decimal,“/”通过重载仅仅支持数据类型:double、decimal,计算的结果类型与输入类型是相同的,这也意味着:

(1)数学运算“+”、“-”,“*”,“%”时可能会出现隐式转换(如int + long => long + long);

(2)数学运算“/”则统一将输入数据转换为数据类型double或decimal进行运算,这一点也意味着,计算结果相应地为数据类型double或decimal。

2. 时间类型(DateType,TimestampType)

DateType可以理解为年、月、日,TimestampType可以理解为年、月、日、时、分、秒,它们分别对着着Python datetime中的date,datetime,使用示例如下:

输出结果:

3. StringType、BooleanType、BinaryType、NoneType

这几种数据类型的使用方法大致相同,就不一一讲解了,注意BinaryType对应着使用了Python中的bytearray。

输出结果:

4. 复合数据类型(ArrayType、MapType、StructType)

复合数据类型共有三种:数组(ArrayType)、字典(MapType)、结构体(StructType),其中数组(ArrayType)要求数组元素类型一致;字典(MapType)要求所有“key”的类型一致,所有“value”的类型一致,但“key”、“value”的类型可以不一致;结构体(StructType)的元素类型可以不一致。

(1)ArrayType

ArrayType要求指定数组元素类型。

(2)MapType

MapType要求指定键(key)类型和值(value)类型。

(3)StructType

StructType包含的元素类型可不一致,需要根据元素的次序依次为其指定合适的名称与数据类型。

综上所述,Spark(Hive)SQL为我们提供了丰富的数据类型,我们需要根据分析数据的实际情况为其选取合适的数据类型(基本类型、复合类型)、尤其是数据类型各自的表示(精度)范围以及数据溢出的情况处理。

python调用spark和调用hive_Spark(Hive) SQL数据类型使用详解(Python)相关推荐

  1. python中集合的元素可以是任意数据类型_详解Python集合数据类型

    本篇介绍Python集合数据类型.集合不同于列表和元组类型,集合存储的元素是无序且不能重复的,同数学中的集合一样,集合可以执行集合的并.交.差运算.通过本篇的学习,可以达成如下目标. ● 掌握集合数据 ...

  2. Python中常见的__init__.py是什么意思?详解Python import的方式和原理

    Python中常见的__init__.py是什么意思?详解Python import的方式和原理 1 什么是模块化编程? 2 __init__.py文件的作用 3 Python如何import第三方库 ...

  3. python 线程安全的数据类型_详解python多线程、锁、event事件机制的简单使用

    详解python多线程.锁.event事件机制的简单使用 发布时间:2020-09-25 02:04:12 来源:脚本之家 阅读:117 作者:君惜 线程和进程 1.线程共享创建它的进程的地址空间,进 ...

  4. python定义类方法用来计算整数的减法运算_详解python的二元算术运算,为什么说减法只是语法糖?...

    原标题:详解python的二元算术运算,为什么说减法只是语法糖? 原题 | Unravelling binary arithmetic operations in Python 作者 | Brett ...

  5. python 正则表达式 断言 不定长表达式_【教程】详解Python正则表达式之: (?!…) negative lookahead assertion 前向否定匹配 /前向否定断言...

    Python 2.7的官网文档中的解释是:(?!...)Matches if ... doesn't match next. This is a negative lookahead assertio ...

  6. 基于python的数据建模与分析案例_基于案例详解Python数据分析与机器学习

    课程概述: 使用数据领域最主流语言Python及其分析与建模库作为核心武器.对于机器学习经典算法给出完整的原理推导并基于实例进行讲解,基于案例演示如何应用机器学习算法解决实际问题. 课程特色: 通俗易 ...

  7. Hive SQL开窗函数详解

    Hive 开窗函数 group by 是分组函数,一组出来一个数据 over() 开窗,针对每一条数据,都有一个独立的组 mk 3 jk 3 mk 3 select orderdate,cost,su ...

  8. python yield from yield_python yield和yield from用法总结详解 python yield和yield from用法总结...

    #!/usr/bin/env python # -*- coding: utf-8 -*-from inspect import isgeneratorfunction def fab(max): n ...

  9. python中参数前面加星号是什么意思_详解Python函数中参数带星号是什么意思

    函数的参数使用除了常规的位置参数和关键字参数外,还支持可变个数的函数参数,这种支持可变个数的参数方法称为参数收集,对应的参数称为收集参数. 一.参数收集的定义 Python的函数支持可变不定数量的参数 ...

最新文章

  1. 行为模式之Observer模式
  2. 关于重装系统或还原系统
  3. jackson使用示例
  4. 学院菌喊你来领取年终学习奖状啦~~!!!
  5. VTK:可视化之RenderLargeImage
  6. Sql Server 2005中的快照隔离
  7. cnpm 安装文件找不到_技术员修复 win7系统word2013找不到标尺工具的处理办法 -win7系统使用教程...
  8. 经营管理者杂志经营管理者杂志社经营管理者编辑部2022年第7期目录
  9. 觅风易语言[1-10]
  10. BOS v2.0后台管理系统界面通用解决方案
  11. 基于vue.js 编写的简单的文件管理器的demo
  12. 软件测试的正反两面性思维,软件测试中破坏性测试思维的思考
  13. 金融计量模型(十):协整和误差修正模型
  14. 计算机教室标语6个字,教室常用标语
  15. linux穷举pppoe密码,Ubuntu/Linux下如何用rp-pppoe3.8通过ADSL上网
  16. 惊讶!一行Python代码让图形秒变「手绘风」
  17. egret 里面设置MovieClip的scale缩放值时,没有效果的情况
  18. 制作在线单词测试的软件,推荐几个在线测试英语单词量的网站
  19. 湖北经济学院计算机,湖北经济学院
  20. 重庆“易法院”上线 民众足不出户参与诉讼全过程

热门文章

  1. OCS Inventory NG使用之在windows 2008 R2平台下安装服务器端(三)
  2. nokia 上的好玩应用(转载)
  3. many-to-many
  4. 左神算法基础班3_13深度拷贝含有随机指针的链表
  5. 经验分享 怎么新建PDF文件
  6. 买了一本老镇的swift语言实战晋级
  7. no copy constructor available or copy constructor is declared #39;explicit#39;
  8. 在线听音乐要收费,你愿意吗?
  9. nodejs使用带用户和密码的Mongo示例
  10. 记住这53个要点提高PHP编程效率