我正在使用Hive连接两个大型表(其中一个超过10亿行,另一个约1亿行):
create table joinedTable as select t1.id, ... from t1 join t2 ON (t1.id = t2.id);
我已经将这两个表以相同的方式进行分桶,通过每个id分成100个桶来进行聚类,但查询仍然需要很长时间。
有什么建议可以加快速度吗?
我正在使用Hive连接两个大型表(其中一个超过10亿行,另一个约1亿行):
create table joinedTable as select t1.id, ... from t1 join t2 ON (t1.id = t2.id);
我已经将这两个表以相同的方式进行分桶,通过每个id分成100个桶来进行聚类,但查询仍然需要很长时间。
有什么建议可以加快速度吗?
当您将数据按连接键分组时,可以使用Bucket Map Join。为此,一个表中的存储桶数量必须是另一个表中存储桶数量的倍数。在查询之前执行set hive.optimize.bucketmapjoin=true;
以激活它。如果这些表不符合条件,Hive将执行普通的内部连接。
如果两个表具有相同数量的存储桶并且数据按存储桶键排序,则Hive可以执行更快的Sort-Merge Join。要激活它,必须执行以下命令:
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找到不同连接技术的一些可视化展示。
在我看来,答案比@Adrian Lange提供的要复杂一些。
首先,必须了解BucketJoin和Sort-Merge Bucket Join (SMBJ)之间非常重要的区别:
要执行bucketjoin,“一个表中的存储桶数量必须是另一个表中存储桶数量的倍数”,如前所述,并且还必须将hive.optimize.bucketmapjoin
设置为true。
发出连接命令后,Hive将在满足上述条件时将其转换为bucketjoin但请注意,Hive不会强制执行分桶!这意味着仅创建具有桶属性的表并不足以将表实际分成指定数量的存储桶,除非将hive.enforce.bucketing
设置为true(这意味着在查询的最终阶段插入数据时减少器的数量实际上被设置为存储桶的数量)。
就性能而言,请注意使用bucketjoin时,单个任务将“较小”的表读入分布式缓存,然后映射器访问该表并执行连接 - 当表具有约100m行时,此阶段可能会非常漫长和低效!
之后,将像在规则连接中一样在减少器中完成连接。
要执行SMBJ,两个表必须具有完全相同数量的桶,以及在这些列上进行排序,并且还要将hive.optimize.bucketmapjoin.sortedmerge
设置为true。
与前面的优化一样,Hive不强制执行分桶和排序,而是假设您确保表实际上被分桶和排序(不仅是通过定义,而是通过设置hive.enforce.sorting
或手动对数据进行排序) - 这非常重要,因为它可能会导致两种情况下的错误结果。
从性能方面来看,这种优化效率更高,原因如下:
请注意以下考虑点:
set hive.input.format = org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
/*+ MAPJOIN(b) */
(出现在select
之后,其中b
是较小的表)还要注意,仅凭这些优化并不总能保证更快的查询时间。
假设您选择进行SMBJ,这会增加在运行连接之前对2个表进行排序的成本-因此您运行查询的次数越多,您为这个排序阶段所“付出”的代价就越少。
有时,简单的连接将带来最佳性能,上述任何优化都不会有所帮助,您必须通过调整MapReduce/Hive设置(如内存使用/并行性等)或在应用程序/逻辑级别优化常规连接过程。
我认为“一个表中的桶数必须是另一个表中桶数的倍数”不是 Map Bucket Join 的必要条件,我们也可以使用相同数量的桶。
WHERE id=123
中。桶是这里最好的选择。 - Adrian LangeCLUSTERED BY (id) INTO 192 BUCKETS
。 - Adrian Langehive.mapjoin.smalltable.filesize
的值,该值指定了Map-side Join中桶的最大大小(以字节为单位)。我建议使用更多的桶,因为无法保证桶的平均填充。 - Adrian Lange