SparkSql的一些问题记录

1.在sparksql打开时(beeline),查询一张表是有数据的,如果此时该表有清洗任务执行,并重新写入数据,那么会出现如下情况

    a.在2.0.2版本,如果此时继续查询数据,那么查询结果为没有记录;如果执行refresh table tablename,那么再次查询可以查询到最新数据;如果关闭beeline之后,再重新查询此表,也会查询到最新数据;

    b.在2.2.1版本,此时查询会报错,提示信息refresh table tablename,执行后再次查询可以查询到最新数据;如果关闭beeline之后,再重新查询此表,也会查询到最新数据;

 

2.sql:select * from tab1 where 分区 in (select 。。。)

    如果普通字段,in 后面接子查询,不会报错

    如果分区字段,in 后面接子查询:

    在2.0.2版本,会报错:Error: java.lang.ArrayIndexOutOfBoundsException: -1 (state=,code=0)

    在2.2.1版本,不会报错

   -------------------------------------------

    在2.0.2,spark还不支持in 后接子查询的写法,默认in ()括号内为具体值,在2.2.1修复了这个问题

    另外,如果想要在2.0.2版本里能够解决这个问题,可以通过参数spark.sql.hive.convertMetastoreParquet来控制

    set spark.sql.hive.convertMetastoreParquet=true  调用spark对parquet文件的处理方法,通过序列化的处理提高了性能,在2.0.2里,打开此参数,spark不能支持in (子查询)的写法

    set spark.sql.hive.convertMetastoreParquet=false 调用的是hive对parquet文件的处理方法,虽然性能差点,但是此时spark是 可以使用 in()的子查询方式,

    这里注意的是,使用了分区 in ()的写法,那么分区的作用就没有了,就会变成普通的字段去处理值的匹配,这个直接导致全表数据的扫描,使性能下降,久而久之,势必对内存资源造成压力。另外,hive的处理方法会生成很多小文件,里面不乏很多空文件,也是性能低的一个原因,spark可以将小文件合并。

 

3.sparksql对分区字段的处理不够聪明

    比如 select distinct 分区 from 。。。当只有分区字段参与计算(最大值,最小值),去重等操作,应该比普通字段有更高的优先级,但是现在的sparksql是将分区字段当做普通字段进行处理,效率太低

 

4.inner join ,left semi join一些总结

    如果出现了2中的场景,如何来避免呢?

    可以通过left semi join来解决

    将in/exists 子查询写在 left semi join的右边,会比用in/exists更高效一点,因为可以set spark.sql.hive.convertMetastoreParquet=true,该参数打开后性能更优

   将需要过滤条件写在on的后面,比如

  SELECT a.key, a.value FROM a

  WHERE a.key in (SELECT b.key FROM B);

可以被重写为:

   SELECT a.key, a.val

   FROM a LEFT SEMI JOIN b on (a.key = b.key);

    这种写法并不能避免全表的扫描,但是你可以在关联分区的时候,提前加一些条件,进行筛选后在关联。

    那这样,为什么不用inner join?

    这里有几个需要注意的地方:

        a.left semi join在进行关联比较的时候,a的一条key值满足条件后,会立马结束比较,返回该条key;而inner join 在关联比较的时候,a表的key值在b中满足条件时,会返回一条key,但是并没有完全结束,该key记录还会继续往下比较,如果还有满足的b表记录,还会返回key,那这样就意味着,a表有一条key,因为b表有多条记录满足,导致inner join后的结果也是多份。这里就是性能的差异,也是结果的差异。

        b.left semi join最终的结果是不可以选出b表的字段,但是inner join可以,这样left semi join会使用更少的内存,传输也会快一点

        c.如果b表key值是唯一的,那么从结果上来看是一样的

    可以执行下面sql体验一下

cache table a select 1 as key;
cache table b select 1 as key union all select 1 as key;
select a.key from a left semi join b on a.key=b.key;
select b.key from a left semi join b on a.key=b.key;
select a.key from a inner join b on a.key=b.key;
select b.key from a inner join b on a.key=b.key;

5.group by的一些问题

2.0.2版本
支持
select a as key,count(1) from table1 group by a;
不支持
select a as key,count(1) from table1 group by key;

2.2.1版本
两种写法都支持

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值