配置单元连接查询优化

i34xakig  于 2021-06-25  发布在  Hive
关注(0)|答案(2)|浏览(362)
Table A
---------
col1, col2,Adate,qty

Table B
-------
col2,cost,Bdate

表大小如下:
a:100万b:70万
考虑以下问题:

SELECT 
  A.col1,
  A.col2,
  B.Bdate bdate,
  SUM(qty)*COLLECT_LIST(cost)[0] price 
FROM A 
JOIN B 
ON (A.col2 = B.col2 AND A.Adate <= B.Bdate) 
GROUP BY 
  A.col1,
  A.col2,
  B.bdate;

上面的配置单元查询在由4个从属(8gb内存,100GB磁盘)和1个主(16GB内存,100GB磁盘)组成的集群上需要3个多小时
这个查询可以优化吗?如果是,在哪里可以进行优化?

o3imoua4

o3imoua41#

使用tez和mapjoin。

set hive.auto.convert.join=true; --this enables map-join
set hive.mapjoin.smalltable.filesize=25000000; --adjust for your smaller table to fit in memory
set hive.execution.engine=tez;

此外,这种计算也不节省内存:

SUM(qty)*COLLECT_LIST(cost)[0] price
``` `COLLECT_LIST` 将组中的所有成本值收集到非唯一(包含组中所有行的值)和无序(是,无序,因为在收集列表之前没有任何distribute+sort)数组中。这个数组可以足够大(元素的数目=组中的行数),这取决于您的数据,然后您要取[0]个元素,这意味着您要从组中随机选取任何成本。收集数组以获得任意元素有意义吗?使用 `min()` 或者 `max` 相反。如果不管是哪一个 `cost` 应该被带走的 `min(cost)` 或者 `max(cost)` 或者其他一些标量函数将消耗更少的内存。您可以使用first\ u值分析函数(可能需要子查询,但也会节省内存)
j2qf4p5b

j2qf4p5b2#

我将尝试为您提供一些建议,以提高中的查询性能 Hive .
检查正在使用的执行引擎

set hive.execution.engine;

如果执行引擎是mr,而不是 MapReduce ,您可以使用 Apache Spark 或者 Apache Tez ,两者都比 MapReduce .

set hive.execution.engine=tez;

连接查询的计算代价很高,而且速度很慢,特别是在连接三个或更多表时,或者在处理非常大的数据时。
可以用来解决这个问题的一种策略是提前连接数据,并将预连接的结果存储在一个单独的表中,然后您可以查询这个表。这是对规范化数据库进行反规范化的一种方法,以使运行分析查询更容易。这种预联接表的方法有一定的成本,但它可以使分析查询更易于编写和运行。
还有一些其他的技术可以改进 Hive 查询性能
联接表排序(最后一个最大的表)
与任何类型的调整一样,了解系统的内部工作非常重要。当配置单元执行连接时,它需要选择哪个表被流化,哪个表被缓存。hive将join语句中的最后一个表用于流式处理,因此我们需要确保这个流式处理表在这两个表中是最大的。
a:100万b:70万
因此,连接这两个表时,较大的表在查询中排在最后是很重要的。
bucketing将数据存储在单独的文件中,而不是像分区那样的单独子目录。
它以一种有效的随机方式划分数据,而不是像划分那样以一种可预测的方式。当记录被插入到一个bucketed表中时,hive计算指定bucketing列中的值的散列码,并使用这些散列码将记录分成bucket。因此,bucketing有时被称为hash分区。bucketing的目标是将记录均匀地分布在预定义数量的bucket上。如果所有联接的表都在联接键列上扣接,扣接可以提高联接的性能。
有关扣合的更多信息,请参阅 Hive 语言手册,描述带扣的表格,
扣板
Hive中的木扣
分区
分区是一种基于特定列(如date、city和department)的值将表划分为相关部分的方法。
配置单元中的每个表都可以有一个或多个分区键来标识特定的分区。使用分区可以很容易地对数据片段进行查询。
apache hive分区

相关问题