Hive - 两个表的高效连接

时间:2013-11-25 17:12:56

标签: optimization join hive buckets

我正在Hive中加入两个大表(一个超过10亿行,一个大约是1亿行),如下所示:

create table joinedTable as select t1.id, ... from t1 join t2 ON (t1.id = t2.id);

我以相同的方式对这两个表进行了冲突,将每个表聚为100个桶,但查询仍然需要很长时间。

有关如何加快速度的任何建议?

3 个答案:

答案 0 :(得分:15)

当您通过连接键分区数据时,您可以使用Bucket Map Join。为此,一个表中的桶数量必须是另一个表中桶数量的倍数。可以通过在查询之前执行set hive.optimize.bucketmapjoin=true;来激活它。如果表格不符合条件,Hive将只执行正常的内部连接。

如果两个表具有相同数量的存储桶并且数据按存储桶键排序,则Hive可以执行更快的排序合并连接。要激活它,您必须执行以下命令:

set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
set hive.optimize.bucketmapjoin=true;
set hive.optimize.bucketmapjoin.sortedmerge=true;

您可以在https://cwiki.apache.org/confluence/download/attachments/27362054/Hive+Summit+2011-join.pdf下找到不同联接技术的一些可视化。

答案 1 :(得分:15)

正如我所看到的,答案比@Adrian Lange提供的要复杂一些。

首先,您必须了解BucketJoin和Sort-Merge Bucket Join(SMBJ)之间的一个非常重要的区别:

要执行 bucketjoin ,“一个表中的存储桶数量必须是另一个表中存储桶数量的倍数”,如前所述,此外必须设置hive.optimize.bucketmapjoin为真。
发布一个联接,如果上述条件发生,hive会将其转换为 bucketjoin 但是注意hive不会强制执行分组!这意味着创建表格不足以使表格实际被划分到指定数量的桶中,因为除非hive.enforce.bucketing设置为true,否则hive不会强制执行此操作(这意味着实际的桶数量)由在查询的最后阶段中将数据插入表格中的reducer数量来设置 从性能方面来看,请注意当使用 bucketjoin 时,单个任务会在映射器访问它并执行连接之前将“较小”表读入分布式缓存中 - 当你的桌子有大约100米的行时,这个阶段可能会非常长且无效! 在病房之后,联接将与在reducers中完成的常规联接相同。

要执行 SMBJ ,除了将hive.optimize.bucketmapjoin.sortedmerge设置为true之外,两个表必须在相同列上具有完全相同数量的存储桶并按这些列排序。
与之前的优化一样,Hive不会强制执行分段和排序,而是假设您确保表格实际上是分段和排序的(不仅是定义,而是通过设置hive.enforce.sorting或在插入时手动排序数据it) - 这非常重要,因为可能导致两种情况下的错误结果 从性能方面来看,由于以下原因,这种优化更有效:

  1. 每个映射器都读取两个存储桶,并且没有单个任务争用分布式缓存加载
  2. 正在执行的连接是合并排序连接,因为数据已经排序,效率更高。
  3. 请注意以下注意事项:

    • 在两种情况下set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
      应该执行
    • 在这两种情况下都应在查询中应用/*+ MAPJOIN(b) */(在select之后,b是较小的表)
    • 有多少桶?
      这应该从这个角度来看:考虑应该严格地应用于更大的表,因为它从这个方向受到更大的影响,后者配置将作为必须应用于较小的表。我认为根据经验,每个桶应包含1到3个块,可能在2个块附近。因此,如果您的块大小为256MB,那么对于我来说,在较大的表中每个桶中有大约512MB的数据是合理的,因此这将成为一个简单的除法问题。

    另外,不要忘记仅仅这些优化并不总能保证更快的查询时间 假设您选择执行SMBJ,这会增加在运行联接之前对2个表进行排序的成本 - 因此运行查询的次数越多,您为此排序阶段“支付”的次数就越少。

    有时,简单的连接将带来最佳性能,并且上述优化都不会有所帮助,您必须在应用程序/逻辑级别或通过调整MapReduce / Hive设置(如内存使用/)来优化常规连接过程并行等等。

答案 2 :(得分:0)

我不认为它是必须的标准"一个表中的桶数量必须是另一个表中桶的数量的倍数"对于地图桶连接,我们也可以有相同数量的存储桶。