BigQuery жалуется после слишком многих операций UNION ALL - почему это происходит и какие у меня варианты? - PullRequest
0 голосов
/ 18 декабря 2018

Я разрабатываю довольно сложный запрос, который требует от меня многократного суммирования данных (т.е. UNION ALL).К моему удивлению, BigQuery не нравится стекирование, и пробный прогон показывает исключение:

Превышены ресурсы во время выполнения запроса: недостаточно ресурсов для планирования запроса - слишком много подзапросов или запрос слишком сложный.

Я выделил точку в запросе, где возникает проблема, чтобы подтвердить, что она кажется слишком большой UNION ALL, вызывающей проблему.Я удивлен, что UNION ALL сделал бы это, но я подозреваю, что я наивен в своих мыслях здесь.

  1. Почему BigQuery не в состоянии справиться с этим дополнительным UNION ALL?Разве сбор данных не является одной из самых простых операций?

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

Вот запрос полностью, хотя я должен отметить, что project.dataset.source_view делаетсначала немного относительно прямой обработки:

WITH p0_funnel AS (
  SELECT  
    date, 
    platform_type, 
    platform, 
    flow,
    step_1, 
    step_2, 
    step_3, 
    step_4, 
    step_5, 
    step_6
  FROM `project.dataset.source_view`
), p1_funnel AS (
  SELECT
    date,
    flow,
    platform_type,
    platform,
    SUM(step_1) AS step_1, 
    SUM(step_2) AS step_2, 
    SUM(step_3) AS step_3, 
    SUM(step_4) AS step_4, 
    SUM(step_5) AS step_5, 
    SUM(step_6) AS step_6
  FROM p0_funnel
  GROUP BY 
    date, 
    flow,
    platform_type,
    platform
), p2_funnel AS (
  SELECT
    date,
    flow,
    platform,
    platform_type,
    step_1,
    step_2,
    step_3,
    step_4,
    step_5,
    step_6
  FROM p1_funnel
), p3_funnel AS (
  SELECT
    date, platform, platform_type, flow,
    'step_1' AS step,
    step_1 AS step_sessions
  FROM p1_funnel

  UNION ALL

  SELECT
    date, platform, platform_type, flow,
    'step_2' AS step,
    step_2 AS step_sessions
  FROM p1_funnel

  UNION ALL

  SELECT
    date, platform, platform_type, flow,
    'step_3' AS step,
    step_3 AS step_sessions
  FROM p1_funnel

  UNION ALL

  SELECT
    date, platform, platform_type, flow,
    'step_4' AS step,
    step_4 AS step_sessions
  FROM p1_funnel

  UNION ALL

  SELECT
    date, platform, platform_type, flow,
    'step_5' AS step,
    step_5 AS step_sessions
  FROM p1_funnel

  UNION ALL

  SELECT
    date, platform, platform_type, flow,
    'step_6' AS step,
    step_6 AS step_sessions
  FROM p1_funnel
), p4_funnel AS (
  SELECT
    main.date,
    platform, platform_type, flow,
    step,
    step_1,
    step_2,
    step_3,
    step_4,
    step_5,
    step_6,
    step_sessions
  FROM p3_funnel AS main
  JOIN p2_funnel USING(date, platform, platform_type, flow)

), funnel_platform_type AS (
  SELECT
    date,
    'platform_type' AS dimension,
    platform_type AS value,
    step,
    step_1,
    step_2,
    step_3,
    step_4,
    step_5,
    step_6,
    step_sessions
  FROM p4_funnel
), funnel_platform AS (
  SELECT
    date,
    'platform' AS dimension,
    platform AS value,
    step,
    step_1,
    step_2,
    step_3,
    step_4,
    step_5,
    step_6,
    step_sessions
  FROM p4_funnel
), funnel_flow AS (
  SELECT
    date,
    'flow' AS dimension,
    flow AS value,
    step,
    step_1,
    step_2,
    step_3,
    step_4,
    step_5,
    step_6,
    step_sessions
  FROM p4_funnel
), p5_funnel AS (
  SELECT * FROM funnel_platform_type UNION ALL
  SELECT * FROM funnel_platform UNION ALL
  SELECT * FROM funnel_flow # including this UNION ALL first introduces the problem
)

SELECT
  date,
  dimension,
  ROW_NUMBER() OVER (PARTITION BY dimension, step ORDER BY step_1 DESC) AS dim_order,
  value,
  step,
  CASE
    WHEN step = 'step_1' THEN 1
    WHEN step = 'step_2' THEN 2
    WHEN step = 'step_3' THEN 3
    WHEN step = 'step_4' THEN 4
    WHEN step = 'step_5' THEN 5
    WHEN step = 'step_6' THEN 6
    ELSE null
  END AS step_order,  
  CASE
    WHEN step = 'step_1' THEN step_2
    WHEN step = 'step_2' THEN step_3
    WHEN step = 'step_3' THEN step_4
    WHEN step = 'step_4' THEN step_5
    WHEN step = 'step_5' THEN step_6
    WHEN step = 'step_6' THEN null
    ELSE null
  END AS next_step_sessions,
  step_1,
  step_2,
  step_3,
  step_4,
  step_5,
  step_6,
  step_sessions
FROM p5_funnel

1 Ответ

0 голосов
/ 19 декабря 2018

Я думаю, что нашел ответ на (2).

Мне все еще не ясно, (1), и я все еще заинтересован.Я могу только предположить, что это связано с внутренней работой BigQuery.

Мое решение (1) использует другую стратегию запросов.В некотором смысле это отделяет тяжелую атлетику от гимнастики, сначала собирая сетку требуемых размеров, используя CROSS JOIN, а затем, во-вторых, просто ПРИСОЕДИНЯЙТЕСЬ к набору данных и обрежьте то, что не требуется.

Вот как это выглядит:

WITH p0_funnel AS (
  SELECT  
    date, 
    platform_type, 
    platform, 
    flow, 
    step_1, 
    step_2, 
    step_3, 
    step_4, 
    step_5, 
    step_6s AS step_6
  FROM `project.dataset.source`
), p1_funnel AS (
  SELECT
    flow,
    platform_type,
    platform,
    SUM(step_1) AS step_1, 
    SUM(step_2) AS step_2, 
    SUM(step_3) AS step_3, 
    SUM(step_4) AS step_4, 
    SUM(step_5) AS step_5, 
    SUM(step_6) AS step_6
  FROM p0_funnel
  GROUP BY 
    flow,
    platform_type,
    platform
), dimension_values AS (
  SELECT DISTINCT
    flow,
    platform_type,
    platform  
  FROM p1_funnel
), dimension_names AS (
  SELECT 'platform_type' AS dimension UNION ALL
  SELECT 'platform' UNION ALL
  SELECT 'flow'
), steps AS (
  SELECT 'step_1' AS step UNION ALL
  SELECT 'step_2' UNION ALL
  SELECT 'step_3' UNION ALL
  SELECT 'step_4' UNION ALL
  SELECT 'step_5' UNION ALL
  SELECT 'step_6'
), full_grid AS (
  SELECT
    dimension,
    step,
    flow,
    platform_type,
    platform  
  FROM dimension_values
  CROSS JOIN dimension_names
  CROSS JOIN steps
)

SELECT
  dimension,
  ROW_NUMBER() OVER (PARTITION BY dimension, step ORDER BY step_1 DESC) AS dim_order,
  CASE
    WHEN dimension = 'platform_type' THEN platform_type
    WHEN dimension = 'platform' THEN platform
    WHEN dimension = 'flow' THEN flow
  ELSE NULL END AS dim_value,
  step,  
  CASE
    WHEN step = 'step_1' THEN 1
    WHEN step = 'step_2' THEN 2
    WHEN step = 'step_3' THEN 3
    WHEN step = 'step_4' THEN 4
    WHEN step = 'step_5' THEN 5
    WHEN step = 'step_6' THEN 6
    ELSE null
  END AS step_order,  
  CASE
    WHEN step = 'step_1' THEN step_1
    WHEN step = 'step_2' THEN step_2
    WHEN step = 'step_3' THEN step_3
    WHEN step = 'step_4' THEN step_4
    WHEN step = 'step_5' THEN step_5
    WHEN step = 'step_6' THEN step_6
    ELSE null
  END AS step_sessions,   
  CASE
    WHEN step = 'step_1' THEN step_2
    WHEN step = 'step_2' THEN step_3
    WHEN step = 'step_3' THEN step_4
    WHEN step = 'step_4' THEN step_5
    WHEN step = 'step_5' THEN step_6
    WHEN step = 'step_6' THEN null
    ELSE null
  END AS next_step_sessions 
FROM full_grid
JOIN p1_funnel USING(platform_type, platform, flow)

CROSS JOIN, кажется, очень полезен при использовании в нужном месте, хотя я все еще не совсем уверен, почему UNION ALL не смогли сделать эту работу.Само собой разумеется, есть технические причины, почему это так, мне интеллектуально любопытно узнать, почему, но, по крайней мере, есть обходной путь для этого случая и других подобных.

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