Оптимизация предложения sum () поверх (order by ...), выдающего ошибку «Превышены ресурсы» - PullRequest
0 голосов
/ 25 марта 2019

Я вычисляю таблицу сеансов на основе данных о событиях с нашего веб-сайта в BigQuery. Таблица событий насчитывает около 12 миллионов событий (довольно мало). После того, как я добавлю логику для создания сеансов, я хочу суммировать все сеансы и назначить global_session_id. Я делаю это, используя предложение sum()over(order by...), которое выдает ошибку превышения ресурсов. Я знаю, что предложение order by вызывает обработку всех данных на одном узле, что приводит к превышению вычислительных ресурсов, но я не уверен, какие изменения я могу внести в свой код для достижения того же результата. Любая работа вокруг, советы или объяснения с благодарностью.

with sessions_1 as ( /* Tie a visitor's last event and last campaign to current event. */

                       select visitor_id as session_user_id,
                              sent_at,
                              context_campaign_name,
                              event,
                              id,
                              LAG(sent_at,1) OVER (PARTITION BY visitor_id ORDER BY sent_at) as last_event,
                              LAG(context_campaign_name,1) OVER (PARTITION BY visitor_id ORDER BY sent_at) as last_event_campaign_name 
                         from tracks_2
                    ),

sessions_2 as ( /* Flag events that begin a new session. */

                   select *,
                   case 
                     when context_campaign_name != last_event_campaign_name
                       or context_campaign_name is null and last_event_campaign_name is not null
                       or context_campaign_name is not null and last_event_campaign_name is null
                       then 1
                     when unix_seconds(sent_at) 
                          - unix_seconds(last_event) >= (60 * 30)
                       or last_event is null
                       then 1 
                       else 0 
                       end as is_new_session
                   from sessions_1
                    ),

sessions_3 as ( /* Assign events sessions numbers for total sessions and total user sessions. */

                     select id as event_id,
                            sum(is_new_session) over (order by session_user_id, sent_at) as global_session_id
                            #sum(is_new_session) over (partition by session_user_id order by sent_at) as user_session_id
                      from  materialized_result_of_sessions_2_query 
                      )
select * from sessions_3

1 Ответ

1 голос
/ 25 марта 2019

If может помочь, если вы определили CTE только с сеансами, а не на уровне событий.Если это работает:

select session_user_id, sent_at,
       row_number() over (order by session_user_id, sent_at) as global_session_id
from  materialized_result_of_sessions_2_query 
where is_new_session
group by session_user_id, sent_at;

Если это не работает, вы можете создать глобальный идентификатор:

. Вы можете присоединить это обратно к исходным данным уровня события, а затем использовать max() функция окна, чтобы назначить его всем событиям.Что-то вроде:

select e.*,
       max(s.global_session_id) over (partition by e.session_user_id order by e.event_at) as global_session_id
from events e left join
     (<above query>) s
     on s.session_user_id = e.session_user_id and s.sent_at = e.event_at;

Если нет, вы можете сделать:

select us.*, us.user_session_id + s.offset as global_session_id
from (select session_user_id, sent_at,
             row_number() over (partition by session_user_id order by sent_at) as user_session_id
      from materialized_result_of_sessions_2_query 
      where is_new_session
     ) us join
     (select session_user_id, count(*) as cnt,
             sum(count(*)) over (order by session_user_id) - count(*) as offset
      from materialized_result_of_sessions_2_query
      where is_new_session
      group by session_user_id
     ) s
     on us.session_user_id = s.session_user_id;

Это может все равно произойти, если почти все пользователи уникальны и сеансы короткие.

...