[英]Hive join query optimisation
Table A
---------
col1, col2,Adate,qty
Table B
-------
col2,cost,Bdate
表格大小如下:
A: 100 万 B: 700k
考虑这个查询:
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;
上面的 hive 查询在 4 个从属设备(8GB memory,100 GB 磁盘)和 1 个主设备(16 GB ZCD69B4957F06CD818D1ZBF3D61980E2)的集群上耗时超过 3 小时
这个查询可以优化吗? 如果是,哪里可以优化?
我将尝试为您提供一些建议以提高Hive
中的查询性能。
set hive.execution.engine;
If you execution engine is mr, rather than MapReduce
, you may be able to use Apache Spark
or Apache Tez
, both of which are faster than MapReduce
.
set hive.execution.engine=tez;
可用于解决此问题的一种策略是预先连接数据并将预连接的结果存储在单独的表中,然后您可以对其进行查询。 这是对规范化数据库进行非规范化的一种方法,可以更轻松地运行分析查询。 这种预连接表的方法有一些成本,但它可以使分析查询更易于编写和运行更快。
还有一些其他技术可以提高Hive
查询性能
与任何类型的调整一样,了解系统的内部工作非常重要。 当 Hive 执行一个连接时,它需要 select 哪个表是流式的,哪个表是缓存的。 Hive 将 JOIN 语句中的最后一个表用于流式传输,因此我们需要确保此流式传输表是两者中最大的。
A: 100 万 B: 700k
因此,当这两个表连接时,较大的表在查询中排在最后是很重要的。
它以有效的随机方式划分数据,而不是像分区那样以可预测的方式划分数据。 将记录插入分桶表时,Hive 计算指定分桶列中值的 hash 代码,并使用这些 hash 代码将记录划分为桶。 出于这个原因,分桶有时被称为 hash 分区。 分桶的目标是将记录均匀地分布在预定义数量的桶中。 如果所有连接的表都在连接键列上进行分桶,则分桶可以提高连接的性能。
有关分桶的更多信息,请参阅描述分桶表的Hive
语言手册的页面,
分区
hive 中的每个表都可以有一个或多个分区键来标识特定分区。 使用分区很容易对数据切片进行查询。
使用 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
会将组中的所有成本值收集到非唯一(包含组中所有行的值)和无序(是的,无序的,因为在 collect_list 之前没有任何分布 + 排序)数组。 该数组可以足够大(元素数 = 组中的行数),具体取决于您的数据,然后您将采用 [0] 元素,这意味着您正在从组中选择任何随机成本。 收集数组以获取任何随机元素是否有意义? 请改用min()
或max
。 如果取哪个cost
无关紧要,那么min(cost)
或max(cost)
或其他一些标量 function 将消耗更少的 memory。 您可以使用 first_value 分析 function (可能需要子查询,但它也会节省内存)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.