在存在的情况下提高更新性能

时间:2011-08-29 11:44:07

标签: sql performance

以下查询将永远运行。有人可以告诉我如何改善其表现吗?

    Query:  update fsa_ip_mth_end_fin_aggregate tbl2
    set (team_acip_gss_sls_cry_am,team_sr_gss_sls_cry_am)  =         
         (select acip_gss_sls_cry_am , sr_gss_sls_cry_am
         from (select agg.current_fsa_ip_id current_fsa_ip_id, 
                       sum(base1.sr_gss_sls_cry_am) sr_gss_sls_cry_am, 
                       sum(base1.acip_gss_sls_cry_am) acip_gss_sls_cry_am  
                from ip_dim base,
                     ip_dim member,
                     ip_team_hierarchy_brdg,
                     fsa_ip_mth_end_fin_aggregate base1,
                     fsa_ip_mth_end_fin_aggregate agg 
                where ip_team_hierarchy_brdg.base_ip_dim_id = base.ip_dim_id 
                and ip_team_hierarchy_brdg.member_ip_dim_id = member.ip_dim_id 
                and ip_team_hierarchy_brdg.active_in = 'Y' 
                and base.dim_active_in = 'Y'
                and member.dim_active_in = 'Y' 
                and base1.current_fsa_ip_id = base.current_fsa_ip_id 
                and agg.current_fsa_ip_id = member.current_fsa_ip_id 
                and ip_team_hierarchy_brdg.allocation_factor != 0 
                and agg.current_fsa_ip_id = base1.current_fsa_ip_id
                group by agg.current_fsa_ip_id) tbl1
            where tbl1.current_fsa_ip_id = tbl2.current_fsa_ip_id)               
where exists                  
(select sr_gss_sls_cry_am,acip_gss_sls_cry_am 
         from (select agg.current_fsa_ip_id current_fsa_ip_id, 
                       sum(base1.sr_gss_sls_cry_am) sr_gss_sls_cry_am, 
                       sum(base1.acip_gss_sls_cry_am) acip_gss_sls_cry_am  
                from ip_dim base,
                     ip_dim member,
                     ip_team_hierarchy_brdg,
                     fsa_ip_mth_end_fin_aggregate base1,
                     fsa_ip_mth_end_fin_aggregate agg 
                where ip_team_hierarchy_brdg.base_ip_dim_id = base.ip_dim_id 
                and ip_team_hierarchy_brdg.member_ip_dim_id = member.ip_dim_id 
                and ip_team_hierarchy_brdg.active_in = 'Y' 
                and base.dim_active_in = 'Y'
                and member.dim_active_in = 'Y' 
                and base1.current_fsa_ip_id = base.current_fsa_ip_id 
                and agg.current_fsa_ip_id = member.current_fsa_ip_id 
                and ip_team_hierarchy_brdg.allocation_factor != 0 
                and agg.current_fsa_ip_id = base1.current_fsa_ip_id
                group by agg.current_fsa_ip_id) tbl1
            where tbl1.current_fsa_ip_id = tbl2.current_fsa_ip_id);    

我尝试了语法:

    update (select query...) 
    set (team_acip_gss_sls_cry_am,team_sr_gss_sls_cry_am) = (select query...) 

但由于涉及的分组/汇总功能,这不起作用。

我也试过'IN'而不是EXISTS。两者的性能几乎相同。请指导我这方面。

1 个答案:

答案 0 :(得分:0)

我将不得不花费更多时间来剖析您的查询,但看起来您在子查询中有未使用的表。查询优化器应该省略它们,但如果不是,则会出现交叉连接和大量行计数通货膨胀。

更新:有很多缺少的连接条件,我甚至无法告诉您要使用此查询实现的目标。 “ip_dim member”和任何其他表之间的关系在哪里? “ip_team_hierarchy_brdg”和“ip_dim base”如何与“fsa_ip_mth_end_fin_aggregate agg”和“fsa_ip_mth_end_fin_aggregate base1”相关联? fsa_ip_mth_end_fin_aggregate上自联接的目的是什么?如果记录之间存在层次关系,则不应在两侧加入相同的字段。

更新2:既然您已经向我们提供了整个查询,那么至少看起来没有任何交叉连接。除了其他人提供的关于确保你有适当索引的建议之外,我对重复的子查询持怀疑态度。第二次尝试你是在正确的轨道上。子查询可以移动到UPDATE的表引用中,但是您需要将表更新与聚合分开。我重构了您的查询以使用ANSI JOIN来更容易地进行故障排除,并移动了子查询:

update fsa_ip_mth_end_fin_aggregate tbl2
join (select agg.current_fsa_ip_id current_fsa_ip_id, 
             sum(base1.sr_gss_sls_cry_am) sr_gss_sls_cry_am, 
             sum(base1.acip_gss_sls_cry_am) acip_gss_sls_cry_am  
        from ip_dim base
        join ip_team_hierarchy_brdg on ip_team_hierarchy_brdg.base_ip_dim_id = base.ip_dim_id 
        join ip_dim member on ip_team_hierarchy_brdg.member_ip_dim_id = member.ip_dim_id 
        join fsa_ip_mth_end_fin_aggregate base1 on base1.current_fsa_ip_id = base.current_fsa_ip_id 
        join fsa_ip_mth_end_fin_aggregate agg on agg.current_fsa_ip_id = member.current_fsa_ip_id 
            and agg.current_fsa_ip_id = base1.current_fsa_ip_id
        where ip_team_hierarchy_brdg.active_in = 'Y' 
        and base.dim_active_in = 'Y'
        and member.dim_active_in = 'Y' 
        and ip_team_hierarchy_brdg.allocation_factor != 0 
        group by agg.current_fsa_ip_id
   ) tbl1
   on tbl1.current_fsa_ip_id = tbl2.current_fsa_ip_id
set tbl2.team_acip_gss_sls_cry_am = tbl1.acip_gss_sls_cry_am,
    tbl2.team_sr_gss_sls_cry_am = tbl1.sr_gss_sls_cry_am            

这是MySQL语法,我刚才意识到你没有指定你的DBMS。 SQL Server对多表UPDATE的语法略有不同,我不确定其他人。

如果我错了并且重复的子查询不是罪魁祸首,那么这个查询结构应该至少可以更容易地优化聚合子查询。