今天想跟大家讨论一下以下几个概念:Filter , Projections, 和 Puchdowns。
1. Filter(过滤) 和 Project(映射)
在传统的 OLAP 系统中,在进行 Join 的时候使用过滤和映射会极大的提高性能。同样的,在 Hadoop 中使用 Filter 和 Projection 同样可以提高效率,由于减少了一个管道需要处理的数据量。在Hadoop中减少处理的数据量是至关重要的,尤其当需要通过网络和本地磁盘进行处理的时候。我们都知道,MapReduce 的shuffle 过程会将数据通过网络写入到磁盘中,所以拥有更少的数据就意味着Job 和 MapReduce 框架的工作量也就越少,这样Job的数据传输也会更快,CPU、磁盘、网络设备的压力也会减少。
使用 filters 和 projection 来减少数据大小
Filter 和 projections 最后靠近数据源进行执行;在MapReduce中,最好在mapper中执行。以下代码显示了一个排除30岁以下的用户,并且只映射他们的姓名和状态:
源码路径:https://github.com/Hanmourang/hiped2/blob/master/src/main/java/hip/ch6/joins/FilterProjection.java
public static class JoinMap extends Mapper<LongWritable, Text, Text, Text> {
@Override
protected void map(LongWritable offset, Text value, Context context)
throws IOException, InterruptedException {
User user = User.fromText(value);
if (user.getAge() >= 30) {
context.write(new Text(user.getName()),
new Text(user.getState()));
}
}
}
在 Join 中使用 filter 需要注意的是,并不是所有连接的数据集都包含你需要过滤的字段。对于这种情况,你需要使用
Bloom filter
方法。该方法将会在后续的 Join 专题进行介绍。
1. Pushdowns
谓词下推(predicate pushdown)属于逻辑优化。优化器可以将谓词过滤下推到数据源,从而使物理执行跳过无关数据。在使用 Parquet 的情况下,更可能存在 文件被整块跳过 的情况,同时系统还通过 字典编码 把字符串对比转换为开销更小的整数对比。在关系型数据库中,谓词则被下推到外部数据库用以减少数据传输。(上面内容摘抄于 Spark新年福音:一个用于大规模数据科学的API——DataFrame)
图片源于:微软发布的 PDW 分析系统
通过以下这张图,我们可以发现,谓词下推在逻辑层面可以理解为利用where 条件中的过滤条件将无用的数据进行筛选掉最终得到需要的行列。
投影和谓词下推通过对存储格式的映射和谓词的推送而进一步来进行过滤。针对 Parquet 这样的存储格式,我们可以直接跳过整个记录或者整个块,这样极大的提高了 Job 的性能并且减少了不必要的开销。
Format | Projection pushdown supported? | Predicate pushdown supported? |
---|---|---|
Text (CSV, JSON, etc.) | No | No |
Protocol Buffers | No | No |
Thrift | No | No |
Avro | No | No |
Parquet | Yes | Yes |
先介绍到这里,接下来会在 Parquet 专题中专门介绍如何利用 Parquet 文件格式来处理谓词下推和映射。
详细请参考:Parquet_1. 使用谓词下推和映射下推来优化 Job
这里有个问题大家有兴趣可以去研究一下:
Issue:在 Hive 中,谓词下推在什么情况会生效,什么情况下回失效?
参考blog :谓词下推失效与生效 (本人觉得博主给出的情况可能与数据相关,会在之后进行测试,有兴趣的朋友可以先研究一下)
需要了解的:
1. 对 Inner Join 来说,Hive 只支持等值连接,不支持不等值连接。因为不等值连接在 MapReduce Job 转换起来很麻烦。
2. 虽然 Hive 不支持等值连接,但是在 Cross Join 和 Where条件中仍然可以使用。下面是 Cross Join发生的条件:
- 使用 Cross Join 关键词
- 只有 Join 关键词,没有 On 条件
- 有 Join 关键词,On 后面跟着绝对为 Ture (例如 1=1) 的情况