SparkSQL与Hive查询不一致问题

1. Hive版本

Hive 1.2.1000.2.6.5.0-292

2.问题背景

交付项目上基本所有的脚本任务,都是使用hive脚本的方式生成数据,但是dolphinscheduler的数据质量sql,是基于sparksql构建的

3.问题现象

在hive里执行sql

    select count(*) from dw_jck_xs_xjjbsj

得到 2023003 条数据
在sparksql里执行同样的sql
得到 0 条数据

4.原因分析

1).分析原因可能是缓存

spark缓存机制: 为了提高性能会缓存Parquet的元数据信息。当通过Hive或其他方式更新了Parquet表时,缓存的元数据信息未更新,导致Spark SQL查询不到新插入的数据。

执行

REFRESH TABLE dw_jck_xs_xjjbsj;

毫无效果,说明和缓存没有关系

2).发现文件存储特点

无意中,看到这个表的hdfs文件存储路径和其他的表不一样,其他的表,都是表名下面直接就是parquet文件,结果他却有子文件件,样式是 “HIVE_UNION_SUBDIR_*”
在这里插入图片描述
查找资料发现: 当Hive表数据存放在多级子目录时,Spark不能识别和读取到数据。

3).子文件夹出现原因

生成dw_jck_xs_xjjbsj表时,使用了如下sql写法

insert overwrite table dw_jck_xs_xjjbsj
select a,b,c from temp_a t1
union all
select a,b,c from temp_b t2

这样生成hdfs文件就会有子文件夹

5.解决方式

1). 方法1修改配置

优缺点: 这个配置就是让spark-sql放弃自己的缓存机制,使用hive的,虽然能用,但是放弃了spark-sql的优势,过于激进,不采用

    -- 在spark-sql里执行
    set spark.sql.hive.convertMetastoreOrc = false; -- 禁用orc格式spark的解析器,使用hive的
    set spark.sql.hive.convertMetastoreParquet=false; -- 禁用parquet格式spark的解析器,使用hive的
    set hive.mapred.supports.subdirectories=true; -- hvie支持子文件夹读取
    set mapreduce.input.fileinputformat.input.dir.recursive=true; -- hvie支持子文件夹读取

2). 方法2修改脚本

制定sql编写规范,采用先把union all的结果写入临时表,再插入结果表

create temporary table temp_dw_jck_xs_xjjbsj as
  select a,b,c from temp_a t1
union all
select a,b,c from temp_b t2
;
insert overwrite table dw_jck_xs_xjjbsj
select a,b,c from dw_jck_xs_xjjbsj
;

6.总结

最终项目上采用代价比较小的修改脚本的方法,并且把这个语法,制定在规范中。

要将SparkSQL读取的数据存入Hive,可以按照以下步骤进行操作: 1. 首先,确保已经正确安装了Java、HadoopSpark、MySQLHive。这样才能顺利进行数据读取和存储的操作。 2. 使用SparkSQL的API连接到MySQL数据库,并将MySQL中的数据加载到Spark的DataFrame或Dataset中。可以使用以下代码实现连接和加载的过程: ``` import org.apache.spark.sql.SparkSession val spark = SparkSession.builder() .appName("SparkSQL Read MySQL Data") .config("spark.sql.warehouse.dir", "/user/hive/warehouse") .enableHiveSupport() .getOrCreate() val mysqlDF = spark.read .format("jdbc") .option("url", "jdbc:mysql://localhost:3306/database_name") .option("dbtable", "table_name") .option("user", "mysql_username") .option("password", "mysql_password") .load() ``` 在上述代码中,需要替换`database_name`、`table_name`、`mysql_username`和`mysql_password`为实际的MySQL数据库信息。 3. 将MySQL中的数据转化为临时表,并注册为临时视图。使用以下代码将DataFrame或Dataset注册为临时视图: ``` val tmpTableName = "tmp_table" mysqlDF.createOrReplaceTempView(tmpTableName) ``` 在上述代码中,将DataFrame或Dataset注册为名为`tmp_table`的临时视图。 4. 接下来,将临时视图中的数据写入Hive表中。使用以下代码将数据写入Hive表: ``` val hiveTableName = "hive_table" spark.sql(s"INSERT INTO TABLE $hiveTableName SELECT * FROM $tmpTableName") ``` 在上述代码中,将临时视图`tmp_table`中的数据插入到名为`hive_table`的Hive表中。 请注意,以上代码只是示例代码,实际操作中需要根据具体情况进行修改和调整。确保MySQLHive的连接信息正确,并且临时表和Hive表的名称与实际情况一致。 这样,就可以通过SparkSQL读取MySQL中的数据,并将数据存入Hive表中了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [sparksql连接mysqlhive](https://download.csdn.net/download/py4Ho123/85265696)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [SparkSql实现Mysqlhive的数据流动](https://blog.csdn.net/weixin_28697603/article/details/113229660)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pengpenhhh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值