Optimization 配置单元-两个表的有效联接

Optimization 配置单元-两个表的有效联接,optimization,join,hive,buckets,Optimization,Join,Hive,Buckets,我在Hive中连接两个大表(一个超过10亿行,一个大约1亿行),如下所示: 我以同样的方式对这两个表进行了压缩,按id将每个表分为100个bucket,但查询仍然需要很长时间 有没有关于如何加快这一进程的建议 通过连接键对数据进行绑定时,可以使用Bucket Map连接。为此,一个表中的桶数量必须是另一个表中桶数量的倍数。可以通过执行set hive.optimize.bucketmappjoin=true激活它在查询之前。如果表不满足条件,配置单元将只执行正常的内部联接 如果两个表具有相同数量

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

我以同样的方式对这两个表进行了压缩,按id将每个表分为100个bucket,但查询仍然需要很长时间


有没有关于如何加快这一进程的建议

通过连接键对数据进行绑定时,可以使用Bucket Map连接。为此,一个表中的桶数量必须是另一个表中桶数量的倍数。可以通过执行
set hive.optimize.bucketmappjoin=true激活它在查询之前。如果表不满足条件,配置单元将只执行正常的内部联接

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

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

您可以在下面找到不同连接技术的一些可视化视图。

在我看来,答案比@Adrian Lange提供的要复杂一些

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

要执行bucketjoin“一个表中的存储桶数量必须是另一个表中存储桶数量的倍数”,如前所述,此外,
hive.optimize.bucketmapjoin
必须设置为true。
发出连接时,如果发生上述情况,hive会将其转换为bucketjoin,但请注意,hive不会强制bucketjoin!这意味着创建带扣的表不足以使表实际扣入指定数量的存储桶,因为除非将
hive.exforce.bucketing
设置为true,否则hive不会强制执行此操作(这意味着实际存储桶的数量是由查询最后阶段将数据插入表中的减缩器数量设置的)。
从性能方面来看,请注意,当使用bucketjoin时,单个任务在映射程序访问“较小”的表并进行连接之前,会将其读入分布式缓存中-当您的表有~100m行时,此阶段可能非常长且无效!
之后,连接将与在减速器中进行的常规连接相同

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

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

    • 在这两种情况下
      设置hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;

      应该执行
    • 在这两种情况下,应在查询中应用
      /*+MAPJOIN(b)*/
      (在
      选择之后,其中
      b
      是较小的表)
    • 有多少桶?
      这应该从这个角度来看:考虑应该严格应用于较大的表,因为它在这个方向上具有更大的影响,而后者,配置必须应用于较小的表。我认为,根据经验法则,每个桶应该包含1到3个块,可能在2个块附近。因此,如果您的block大小是256MB,我认为在较大的表中每个存储桶中有~512MB的数据是合理的,因此这成为一个简单的划分问题
    另外,不要忘记,单靠这些优化并不总能保证更快的查询时间。
    假设您选择执行SMBJ,这会增加在运行联接之前对2个表进行排序的成本-因此,运行查询的次数越多,您为此排序阶段“支付”的费用就越少


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

    我认为这不是必须的标准“一个表中的存储桶数量必须是另一个表中存储桶数量的倍数"对于map bucket join,我们也可以有相同数量的bucket。

    我来试一试。索引在Hive中有帮助吗?即,如果我用id对t1和t2进行索引,索引不会提高join中的性能。它们用于检索单行,例如在
    中,其中id=123
    。bucket是这里的最佳选择。您可以指定数量通过附加以下内容创建表时的存储桶数:
    CLUSTERED by(id)进入192个Bucket
    很抱歉,我读错了。列值是按Bucket的数量散列的。将id列(应该有不同的值)拼成Bucket可以确保一致性。通过使用Bucket Map Join,Hive对Bucket执行公共Map-side连接。因此,Bucket的数量取决于表的大小和值e of
    hive.mapjoin.smalltable.filesize
    ,在本例中,它指定了映射端连接的最大存储桶大小(以字节为单位)。我建议最好使用更多存储桶,因为不能保证存储桶的填充均匀。
    set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
    set hive.optimize.bucketmapjoin=true;
    set hive.optimize.bucketmapjoin.sortedmerge=true;