1.hive和spark查询不一致(parquet版本问题)

org.apache.parquet.io.ParquetDecodingException: Can not read value at 0 in block -1 in file xxx spark产出的数据hive查询异常报错Can not read value at 0 in block -1 in file xxx hive查询: Demo-查询不一致(持续更新) - 图1

spark查询: Demo-查询不一致(持续更新) - 图2 解决方式:spark产出数据时添加参数conf spark.sql.parquet.writeLegacyFormat=true

原因: 设置为true时,数据会以Spark1.4和更早的版本的格式写入。比如decimal类型的值会被以Apache Parquet的fixed-length byte array格式写出,该格式是其他系统例如Hive、Impala等使用的。 设置为false时,会使用parquet的新版格式。例如,decimals会以int-based格式写出。如果Spark SQL要以Parquet输出并且结果会被不支持新格式的其他系统使用的话,需要设置为true。

2.impala查询和spark不一致(json表支持问题)

用户业务sql使用impala和spark查询的数据量不一致,impala数据多 解决方式:暂时以spark查询的结果为准。

spark查询:

Demo-查询不一致(持续更新) - 图3

impala查询:

Demo-查询不一致(持续更新) - 图4

原因: 表为json表 ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'

社区impala目前是不支持读,开发怀疑有bug,目前建议等社区JSON表功能,先用spark读。

3.spark和impala执行不一致的问题(函数使用姿势有区别)

impala: Demo-查询不一致(持续更新) - 图5

spark: Demo-查询不一致(持续更新) - 图6

原因: 如报错,spark的isnull函数不允许传两个参数。也咨询了spark开发,isnull 只接收一个参数,这里同一个函数,impala和spark有区别,会对用户造成困扰。类似的函数使用姿势不同的问题。希望能有一个说明手册,方便用户使用。

4. 修改字段查询null(参数问题)

直接使用alter table对hive表修改字段名称,修改后hive和spark和impala均为null 原因: hive和spark和impala均是按列名查parquet文件,修改列名后目前查询均为null解决方式如下 hive查询解决方式 执行ALTER TABLE dwd.dwd_bixin_trade_sviporder_di_123 SET TBLPROPERTIES ('parquet.column.index.access'='true');或者set parquet.column.index.access = true可正常查询,希望可以配置默认该参数为true),目前内部环境该配置应该都没有默认true。 spark解决方式: 与hive类似 spark.sql.hive.convertMetastoreParquet=false parquet.column.access.index=true 如果设置了 spark.sql.hive.convertMetastoreParquet=false,那就跟 Hive 行为相同;否则忽略这个参数 impala解决方式 目前集群查询parquet配置默认都是name Demo-查询不一致(持续更新) - 图7

如需解决这种情况,需要手动在代码前set PARQUET_FALLBACK_SCHEMA_RESOLUTION = position 但该种情况如果是增删列,且不是最后一列,由于查询按position位置,会导致错位。

5.spark和impala查询不一致(函数原理不同)

spark正常 Demo-查询不一致(持续更新) - 图8 impala乱码 Demo-查询不一致(持续更新) - 图9 原因:

Demo-查询不一致(持续更新) - 图10

impala的substr切割得以3个字符为单位,每3个byte是一个中文字符【impala一个中文 3个字符单位】 Demo-查询不一致(持续更新) - 图11 这里和spark有区别。用户在查询时不会直接清楚怎么去规避这个问题。

6.spark和impala查询不一致(spark有隐式转换)

spark正常 Demo-查询不一致(持续更新) - 图12 impala无数据 Demo-查询不一致(持续更新) - 图13

原因: 这是由于datesub类的时间函数和本身过滤的分区条件例如ds的类型不同。我们需要cast成一样的类型。 Demo-查询不一致(持续更新) - 图14

例如datesub这种时间函数,返回的都是datetime类型的字段,这里表的分区字段ds的字段类型是string。在spark中可能会做隐式转换并去过滤数,在impala中不会这样。所以需要将datesub返回的dateatime强转为string。结果才能保持一致。很多类似的问题都是这个原因。

7.spark和impala查询不一致(实现方式不一样)

该函数用法: Demo-查询不一致(持续更新) - 图15 impala正常: Demo-查询不一致(持续更新) - 图16

spark获取为null Demo-查询不一致(持续更新) - 图17

提取的url如下 Demo-查询不一致(持续更新) - 图18

原因:这是因为spark和impala内部实现逻辑不一样,Spark 是调用 java.net.URI。java方法判断url中带{}的是非法的url。所以这个函数分析不出对应的字段。而impala的函数底层逻辑是C++实现的。支持识别这种url。

结论:如果数据格式一定是这样,可以使用impala引擎,或者通过自己写udf的形式,使用spark实现。

8.spark离线开发查询没有数据,自助分析有数据(spark版本差异)

离线开发: Demo-查询不一致(持续更新) - 图19 Demo-查询不一致(持续更新) - 图20

自助分析: Demo-查询不一致(持续更新) - 图21

原因:spark3修改了日期类型的隐式转换规则,spark里的日期和字符串比较会转换成日期和日期比较,spark2里的日期和字符串比较会转换成字符串和字符串比较。 Demo-查询不一致(持续更新) - 图22

结论:如果是离线开发spark2运行,会直接比较字符串,那么直接比较后,数据可能会过滤不到,造成没有结果的问题。需要自行截断字符串处理。

9.spark自助分析可以运行,hive自助分析报错格式问题(sparksql于hive有语法差异)

Demo-查询不一致(持续更新) - 图23 如图,hive无法运行。自助分析spark可以运行。

原因:

Demo-查询不一致(持续更新) - 图24

sparksql和hive的语法不一样,hive不支持on子句中用or

10.Hive select有数据但是select count(*) 的结果不对

添加参数:set hive.compute.query.using.stats=false;

11.spark3写入数据,spark查询正常,hive引擎查询无数据

Demo-查询不一致(持续更新) - 图25
表分区字段为timestamp类型,hive string 转timestamp需强制转换,无法隐式转换。推荐用户修改表分区字段类型到string类型即可


作者:刘思伟