spark ORC原理

orc历史

  ORC的全称是(Optimized Row Columnar),ORC文件格式是一种Hadoop生态圈中的列式存储格式,它的产生早在2013年初,最初产生自Apache Hive,用于降低Hadoop数据存储空间和加速Hive查询速度。

orc结构–----hdfs上的物理视图

  

orc结构----逻辑视图

orc存储结构解析

    orc文件有如下结构快:block,stripe,row_group,stream,index data,Row data,fileFooter,postscript

    orc在hdfs上存储,为适应hdfs区块存储思想会将orc文件划分成block块,orc的block块大小一般和hdfs的block块大小一致通过配置( hive.exec.orc.default.block.size 默认256M)指定。每个block块中包含多个stipe,stipe大小通过参数( hive.exec.orc.default.stripe.size 默认64M)指定。应尽量避免strip跨hdfs:block存储,否则在解析stipe时会存在IO跨节点的数据请求,从而增加了系统资源开销。所以,一般orc:block块大小是orc:stripe大小的整数倍。但是,在有些情况下还是会出现block块不能够被整数个stipe完整填满,需要关闭跨hdfs:block的数据存储,需要指定(hive.exec.orc.default.block.padding=false)关闭块存储。另外需要指定最小磁盘利用空间( hive.exec.orc.block.padding.tolerance 默认0.05,例如orc:block=256M,256*0.05=12.5M),hdfs:block块剩余磁盘空间低于此值将放弃使用。

orc on spark

   1. 在spark上如何使用配置调优

        df.write.option(“”,””).orc(“path”)

        df.write.format(“”).option(“”,””).save(“path”)

        df.write.format(“”).option(“”,””).saveAsTable(“”)

       

       create table tablename(

           col1 STRING,

           col2 STRING

       )stored as orc tblproperties ("orc.compress"="NONE");

   2.在spark环境下可用的调优配置    

 

Orc配置

Hive别名

默认值

描述

orc.stripe.size

 hive.exec.orc.default.stripe.size

 64M

Stripe大小

orc.block.size

 hive.exec.orc.default.block.size

 256M

默认bolck块大小

orc.create.index

 orc.create.index

 true

是否创建索引

orc.row.index.stride

 hive.exec.orc.default.row.index.stride

10000

默认索引块大小

orc.compress.size

 hive.exec.orc.default.buffer.size

256kb

读写缓冲区大小

orc.base.delta.ratio

 hive.exec.orc.base.delta.ratio

8

Stripe_size/buffer_size

orc.block.padding

 hive.exec.orc.default.block.padding

 true

Stripe不跨block块

orc.compress

 hive.exec.orc.default.compress

 ZLIB

默认压缩

orc.write.format

 hive.exec.orc.write.format

0.12

写文件的版本Hive 0.12 使用RLE

orc.encoding.strategy

 hive.exec.orc.encoding.strategy

 speed/compression

编码策略:只影响数值格式,不会改变高级编码(zlib,snappy)

orc.compression.strategy

 hive.exec.orc.compression.strategy

speed/compression

压缩策略,会改变高级压缩解码器的的压缩级别(zlib,snappy)

orc.block.padding.tolerance

 hive.exec.orc.block.padding.tolerance

 0.05D

最小block碎片填充阈值(hdfs block=256::12.5M,64M::3.2M

orc.bloom.filter.fpp

 orc.default.bloom.fpp

 0.05D

布隆过滤器误差概率

orc.use.zerocopy

 hive.exec.orc.zerocopy

 false

开启零拷贝

orc.skip.corrupt.data

 hive.exec.orc.skip.corrupt.data

 false

跳过不正确的数据

orc.tolerate.missing.schema

 hive.exec.orc.tolerate.missing.schema

 true

修复bug: HIVE-4243

orc.memory.pool

 hive.exec.orc.memory.pool

 0.5D

写orc时使用的最大堆空间比例

orc.dictionary.key.threshold

 hive.exec.orc.dictionary.key.size.threshold

 0.8D

基元数据与数据条数比例查过阈值将关闭字典编码

orc.dictionary.early.check

 hive.orc.row.index.stride.dictionary.check

 true

在10000行之后是否开启字典检查

orc.bloom.filter.columns

 orc.bloom.filter.columns

 

布隆过滤器的列

orc.bloom.filter.write.version

 orc.bloom.filter.write.version

 original/utf-8

布隆过滤器的版本,original:使用两个版本的布隆过滤器,否则只是用utf-8

orc.bloom.filter.ignore.non-utf8

 orc.bloom.filter.ignore.non-utf8

 false

是否忽略过时的非utf-8过滤器

orc.max.file.length

 orc.max.file.length

 long.max

支持最大orc文件大小

orc.mapred.input.schema

 (String)null

 (Object)null

Hadoop,mapRed读取orc

orc.mapred.map.output.key.schema

 (String)null

 (Object)null

 

orc.mapred.map.output.value.schema

 (String)null

 (Object)null

 

orc.mapred.output.schema

 (String)null

 (Object)null

 

orc.include.columns

 hive.io.file.readcolumn.ids

 (Object)null

 

orc.kryo.sarg

 orc.kryo.sarg

 (Object)null

 

orc.sarg.column.names

 org.sarg.column.names

 (Object)null

 

orc.force.positional.evolution

 orc.force.positional.evolution

 false

hive2.1之后支持(使用位置匹配,而不是不使用列名称匹配顶级列)

orc.write.variable.length.blocks

 

false

是否使用可变长度的hdfs块,hdfs2.7之后支持
   spark.sql.orc.filterPushdown  false  spark查询orc时是否开启位于下推功能

异常及原因分析

 1. 异常 java.io.EOFException:缓存(ArrayBuffer)分配出错

 

2. Malformed ORC file /xx/xx/xx.orc. Invalid postscript length

    原因:文件损坏/文件为非orc文件

    原因分析:读取orc时,先从文件的最后读取16kb。而最后一个字节存放postScript的长度,如果最后一个字节的长度小于length("orc")+1,说明文件已经postScript已经损坏,会抛出以上异常。因为即使空的orc文件,在postScript至少包含“orc”和压缩格式 长度一定大于4

    解决方案:1:重新执行一次:在读取的16kb出现系统抖动,导致读取错误。

                      2.重新生成数据文件

   源码展示:

 public static final String MAGIC = "ORC";
 int psLen = buffer.get(readSize - 1) & 0xff;
 int len = OrcFile.MAGIC.length();
 if (psLen < len + 1) {
       throw new IOException("Malformed ORC file " + path + ". Invalid postscript length " + psLen);
    }

 3.Malformed ORC file /xx/xx.orc . Invalid postscript

   原因:要读取的文件不是ORC文件/文件损坏

   原因分析:在2过程校验完成后,接着校验16kb中的[0,4]序列化后的数据是否为"ORC"字符串。因为ORC格式的文件在序列化后最后16kb中的[0,4]序列化后为“ORC"。

   解决方案:1.检查hive的数据文件是否为orc格式,有可能数据文件中的一个或几个为非orc文件,hive中序列化和反序列化方式却是orc,尝试用spark-shell中的spark.read.orc("报错文件").count,是否依然报错

                     2.文件损坏,重新生成相应文件

   源码展示:

 if (!Text.decode(header, 0 , len).equals(OrcFile.MAGIC)) {
       throw new IOException("Malformed ORC file " + path + ". Invalid postscript.");
    }

 4. ORC file /xx/xx.. was written by a future Hive version " + versionString(version) + ". This file may not be readable by this version of Hive

   原因:Orc文件的序列化版本小于当前规定版本,可能会导致数据错误,提示警告

   原因分析:文件生成和使用不是同一个版本OrcFile

   解决方案:1. 降低hive/spark版本,2.按照当前读取的hive版本重新生成orc文件

   源码展示:

 V_0_11("0.11", 0, 11),
 V_0_12("0.12", 0, 12);
 public static final Version CURRENT = V_0_12;
 if (major > OrcFile.Version.CURRENT.getMajor() || (major == OrcFile.Version.CURRENT.getMajor() && minor > OrcFile.Version.CURRENT.getMinor())) {
        log.warn("ORC file " + path + " was written by a future Hive version " +  versionString(version) + ". This file may not be readable by this version of Hive.");
      }
 

5.Unknown compression

原因:写数据时使用了不支持的压缩格式,暂时只支持 NONE ZLIB SNAPPY LZO。文件损坏

原因分析:序列化出现问题,导致postscript出现错误,读取postscript的压缩配置出现问题

解决方案:重新生成数据文件,使用支持的压缩格式

源码展示:

       switch (ps.getCompression()) {

    case NONE:
      break;
 case ZLIB:
      break;
 case SNAPPY:
      break;
 case LZO:
      break;
 default:
      throw new IllegalArgumentException("Unknown compression");
6:LZO is not available.  ClassNotFoundException
 LZO is not available. IllegalArgumentException
 Problem initializing LZO IllegalArgumentException
 Insufficient access to LZO IllegalArgumentException
 
原因:使用LZO作为压缩格式,却在系统中无法找到/无法初始化压缩器

原因分析:其他的压缩格式是通过new的方式初始化压缩器,在源码打包时就能做依赖完整性校验。但是lzo却是通过反射的方式获取,spark唯独没有重写lzo的压缩器。而是通过反射复用hive保重的lzo压缩器。当版本不匹配,或者依赖包不完整时,就有如下异常。

解决方式:1. 检查依赖包, 2.检查hive和spark的版本是否匹配

源码展示:

switch (kind) {
  case NONE:
    return null;
 case ZLIB:
    return new ZlibCodec();
 case SNAPPY:
    return new SnappyCodec();
 case LZO:
    try {
      Class lzo = (Class) JavaUtils.loadClass("org.apache.hadoop.hive.ql.io.orc.LzoCodec");
 return lzo.newInstance();
 } catch (ClassNotFoundException e) {
      throw new IllegalArgumentException("LZO is not available.", e);
 } catch (InstantiationException e) {
      throw new IllegalArgumentException("Problem initializing LZO", e);
 } catch (IllegalAccessException e) {
      throw new IllegalArgumentException("Insufficient access to LZO", e);
 }

你可能感兴趣的:(大数据,spark,orc)