Улучшить производительность обновления там, где есть - PullRequest
0 голосов
/ 29 августа 2011

Приведенный ниже запрос выполняется вечно. Может кто-нибудь подскажите, пожалуйста, как улучшить его производительность?

    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...) 

Но это не сработало из-за задействованных групповых / агрегатных функций.

Я также попробовал «В» вместо «СУЩЕСТВУЕТ». Оба имеют почти одинаковую производительность. Пожалуйста, направьте меня в этом отношении.

1 Ответ

0 голосов
/ 29 августа 2011

Мне придется потратить больше времени на анализ вашего запроса, но, похоже, у вас есть неиспользуемые таблицы в подзапросах. Оптимизатор запросов должен пропустить их, но если это не так, вы получите перекрестное соединение и значительное увеличение числа строк.

Обновление: так много пропущенных условий соединения, что я даже не могу сказать, чего вы пытаетесь достичь с помощью этого запроса. Где связь между «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, я только что понял, что вы не указали свою СУБД. SQL Server имеет несколько другой синтаксис для нескольких таблиц UPDATE, в других я не уверен.

Если я ошибаюсь и повторный подзапрос не является виновником, эта структура запроса должна, по крайней мере, упростить оптимизацию подзапроса агрегации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...