【问题标题】:How to optimise a query on a large dataset?如何优化对大型数据集的查询?
【发布时间】:2017-09-18 17:55:16
【问题描述】:

我原来的查询 -

CREATE TABLE admin.FctPrfitAmt_rpt AS 
SELECT rcn.* FROM 
(SELECT t1.* FROM (SELECT * FROM admin.FctPrfitAmt t2 WHERE t2.scenario_id NOT IN(SELECT DISTINCT t3.scenario_id FROM admin.FctPrfitAmt_incr t3)
UNION ALL
SELECT * FROM admin.FctPrfitAmt_incr) t1) rcn;

问题是目前这个查询需要很多时间,因为涉及的记录数量很多。

有没有办法调整这个查询?

我尝试了这种方法,但它不起作用 -

CREATE TABLE admin.FctPrfitAmt_rpt AS
SELECT * FROM admin.FctPrfitAmt t2 
WHERE t2.scenario_id NOT exists (SELECT 1 from  admin.FctPrfitAmt_incr t3 where t2.scenario_id = t3.scenario_id)
UNION ALL
SELECT * FROM admin.FctPrfitAmt_incr 

错误 - 我的 Hive 版本不支持“不存在”,所以对于我的方法,我收到以下错误:

编译语句时出错:FAILED: ParseException line 3:25 cannot identify input near 'NOT' 'exists' '(' in expression specification

【问题讨论】:

  • (1) scenario_id 在两个表中都是唯一的吗? (2) 表的大小(行/字节)是多少?
  • 是,但查询失败;有什么办法可以让“不存在”工作?
  • 嗨,你能回答我第一条评论中的两个问题吗?
  • 对不起,我错过了。 #-> hdfs dfs -du -h -s /user/admin/FctPrfitAmt 30.7 G 61.3 G /user/admin/FctPrfitAmt [root@itsusraedld05:/root]# #-> hdfs dfs -du -h -s /user/ admin/FctPrfitAmt_incr 2.2 G 4.3 G /user/admin/FctPrfitAmt_incr 方案 id 在两个表中都不是唯一的
  • 您的数据可能存在偏差。请显示以下查询的结果:select scenario_id,pa,pfa,pa*pfa as product from ( select scenario_id ,count(case when tab = 1 then 1 end) as pa ,count(case when tab = 2 then 1 end) as pfa from ( select 1 as tab,scenario_id from admin.FctPrfitAmt as pa union all select 2 as tab,scenario_id from admin.FctPrfitAmt_incr as pfa ) t group by scenario_id ) t order by product desc limit 10 ;

标签: performance hadoop hive bigdata


【解决方案1】:
  1. 您的语法错误。 NOT EXISTS 前面不应有 t2.scenario_id
  2. 正如我们所见,scenario_id 在两个表上都有偏差,这会在连接上产生巨大的积。

select  * 
from    admin.FctPrfitAmt   pa
where   not exists 
        (
            select  null

            from   (select  distinct 
                            pfa.scenario_id 

                    from    admin.FctPrfitAmt_incr  pfa
                    ) pfa

            where   pfa.scenario_id = 
                    pa.scenario_id
        )

union all

select  * 
from    admin.FctPrfitAmt_incr 

【讨论】:

  • 谢谢先生,它可以工作,但在性能方面,它与原始查询所用的时间相同。你能建议我如何让它高效吗?解释计划让我很困惑,所以不确定如何进行。
  • 对不起,我错过了。 #-> hdfs dfs -du -h -s /user/admin/FctPrfitAmt 30.7 G 61.3 G /user/admin/FctPrfitAmt [root@itsusraedld05:/root]# #-> hdfs dfs -du -h -s /user/ admin/FctPrfitAmt_incr 2.2 G 4.3 G /user/admin/FctPrfitAmt_incr 方案 id 在两个表中都不是唯一的 –
  • 好的,我会检查一下,我应该使用镶木地板格式还是尝试使用场景 ID 来提高性能
  • 两者都可能提高性能,但主要问题是scenario_id的产物
  • 我创建了镶木地板表并使用了您建议的查询,性能更好。非常感谢。从在开发环境中花费 14 分钟的原始查询开始,新查询在不到 8 分钟的时间内运行。太神奇了,我如何检查/验证修改后的查询(最终报告表中的数据)和预期的 o/p(使用原始查询)生成的 o/p 是否相同。
【解决方案2】:

您最好在“选择输入”部分中加入 2 个表并过滤掉连接键上不为空的行。

CREATE TABLE admin.FctPrfitAmt_rpt AS 
    SELECT rcn.* FROM 
    (
        SELECT t1.* 
        FROM admin.FctPrfitAmt t1 
        LEFT JOIN admin.FctPrfitAmt_incr t2
        ON t1.scenario_id = t2.scenario_id
        WHERE t2.scenario_id IS NULL
        UNION ALL
        SELECT * FROM admin.FctPrfitAmt_incr
    ) rcn
;

【讨论】:

  • 感谢您的建议。有这么多数据,我希望我不会遇到内存问题。我的目标是减少执行时间。我是否也应该尝试将数据聚集在场景 ID 上。对不起,我是这个话题的新手。所以检查。
  • 我相信它会根据加入阶段的scenario_id对数据进行聚类,因为这是该阶段的映射键。您可以通过将“EXPLAIN”附加到您的查询并运行它来验证这一点。为了节省内存,您还应该确保表按从小到大的顺序连接。
  • 谢谢。增量表小于基表。但是会以这种方式离开加入工作。我尝试了您建议的查询。它因容器限制内存问题而失败:(
  • 如果是这种情况,您可以按照上面相反的顺序正确加入表格。
【解决方案3】:
select  *

from   (select  *
               ,max(tab) over (partition by scenario_id) as max_tab

        from    (           select *,1 as tab from master.FctPrfitAmt
                union all   select *,2 as tab from master.FctPrfitAmt_incr
                ) t
        ) t

where   tab     = 2
     or max_tab = 1
;

如果您的所有数据都由原始类型(没有数组、地图等)组成,
您可以使用以下查询:

select  inline(array(original_rowset))

from   (select  original_rowset
               ,tab
               ,max(tab) over (partition by scenario_id) as max_tab

        from    (           select struct(*) as original_rowset,scenario_id,1 as tab from FctPrfitAmt
                union all   select struct(*) as original_rowset,scenario_id,2 as tab from FctPrfitAmt_incr
                ) t
        ) t

where   tab     = 2
     or max_tab = 1

【讨论】:

  • 请试试这个。它有可能比其他选项更快。请注意,最终结果将包含 2 个额外的技术字段(tabmax_tab),因此您可能希望将外部的 * 替换为相关列。
  • 好的,谢谢,会尝试检查,但在这种情况下(使用附加列),如果我需要为每个表提供列名,我不能将其用作这么多表的通用解决方案,当它正在处理中。
  • 你能帮我理解一下,我们在这里想要做什么。我理解你之前的解决方案。请多多包涵,我是菜鸟..
  • struct(*) 创建一个包含所有表字段的结构。 inline(array(original_rowset)) 将结构分解为单独的字段。
  • 是的,以下是数字..Details 原始查询 -> 总计:706 个映射器 31 个减速器;修改后的查询 -> 总计 - 159 个映射器,18 个减速器 CPU 时间也从 6 小时 50 分钟减少到 3 小时 58 分钟
猜你喜欢
  • 2017-12-11
  • 1970-01-01
  • 2015-02-22
  • 1970-01-01
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 2018-03-07
相关资源
最近更新 更多