Chrome UX Report: повышение производительности запросов - PullRequest
0 голосов
/ 21 января 2020

Я запрашиваю набор данных Chrome UX Report publi c, используя следующий запрос, чтобы получить значения для указанных метрик с течением времени для набора таблиц c, специфичных для страны. Запрос выполняется очень долго (я остановил его на 180 секунд), потому что я не знаю, каково время ожидания для запроса или как определить, завис запрос.

Я пытаюсь получить агрегированные данные за год для среднего_фкп , среднего_фп и среднего_дкл . Я не уверен, правильно ли я использую BigQuery или есть способы оптимизировать запрос, чтобы он работал быстрее

Этот запрос я использую.

SELECT
  _TABLE_SUFFIX AS yyyymm,
  AVG(fcp.density) AS average_fcp,
  AVG(fp.density) as average_fp,
  AVG(dcl.density) as average_dcl
FROM
  `chrome-ux-report.country_cl.*`, 
  UNNEST(first_paint.histogram.bin) as fp,
  UNNEST(dom_content_loaded.histogram.bin) as dcl,
  UNNEST(first_contentful_paint.histogram.bin) AS fcp
WHERE
  form_factor.name = 'desktop' AND
  fcp.start > 20000
GROUP BY
  yyyymm
ORDER BY
  yyyymm

Ответы [ 3 ]

3 голосов
/ 22 января 2020

Я не уверен, имеет ли математический смысл получение AVG() всех плотностей - но давайте сделаем это в любом случае.

Большая проблема в запросе заключается в следующем:

  UNNEST(first_paint.histogram.bin) as fp,
  UNNEST(dom_content_loaded.histogram.bin) as dcl,
  UNNEST(first_contentful_paint.histogram.bin) AS fcp

- это взрывное соединение: оно превращает одну строку с 3 массивами по ~ 500 элементов в 125 миллионов строк !!! Вот почему запрос не выполняется.

Аналогичный запрос, который дает похожие результаты:

SELECT yyyymm,
  AVG(average_fcp) average_fcp,
  AVG(average_fp) average_fp,
  AVG(average_dcl) average_dcl
FROM (
  SELECT
     _TABLE_SUFFIX AS yyyymm,
    (SELECT AVG(fcp.density) FROM UNNEST(first_contentful_paint.histogram.bin) fcp WHERE fcp.start > 20000) AS average_fcp,
    (SELECT AVG(fp.density) FROM UNNEST(first_paint.histogram.bin) fp) AS average_fp,
    (SELECT AVG(dcl.density) FROM UNNEST(dom_content_loaded.histogram.bin) dcl) AS average_dcl
  FROM `chrome-ux-report.country_cl.*` 
  WHERE form_factor.name = 'desktop'  
)
GROUP BY yyyymm
ORDER BY yyyymm

Хорошая новость: этот запрос выполняется за 3,3 секунды.

Теперь, когда запрос выполняется за 3 секунды, самый важный вопрос: имеет ли он математический смысл?

enter image description here


Бонус: этот запрос более логичен для математики, но я не уверен на 100%:

SELECT yyyymm,
  AVG(average_fcp) average_fcp,
  AVG(average_fp) average_fp,
  AVG(average_dcl) average_dcl
FROM (
  SELECT yyyymm, origin, SUM(weighted_fcp) average_fcp, SUM(weighted_fp) average_fp, SUM(weighted_dcl) average_dcl
  FROM (
    SELECT
       _TABLE_SUFFIX AS yyyymm,
      (SELECT SUM(start*density) FROM UNNEST(first_contentful_paint.histogram.bin)) AS weighted_fcp,
      (SELECT SUM(start*density) FROM UNNEST(first_paint.histogram.bin)) AS weighted_fp,
      (SELECT SUM(start*density) FROM UNNEST(dom_content_loaded.histogram.bin)) AS weighted_dcl,
      origin
    FROM `chrome-ux-report.country_cl.*`   
  )
  GROUP BY origin, yyyymm
)
GROUP BY yyyymm
ORDER BY yyyymm

enter image description here

2 голосов
/ 21 января 2020

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

Запрос выполнялся в течение 4 секунд. Синтаксис:

SELECT
  _TABLE_SUFFIX AS yyyymm,
  AVG(fcp.density) AS average_fcp,
FROM
  `chrome-ux-report.country_cl.*`, 
  UNNEST(first_contentful_paint.histogram.bin) AS fcp
WHERE
  form_factor.name = 'desktop' AND
  fcp.start > 20000
GROUP BY
  yyyymm


UNION ALL 

SELECT
  _TABLE_SUFFIX AS yyyymm,
  AVG(fp.density) as average_fp,

FROM
  `chrome-ux-report.country_cl.*`, 
  UNNEST(first_paint.histogram.bin) as fp
WHERE
  form_factor.name = 'desktop' 
GROUP BY
  yyyymm

UNION ALL 

SELECT
  _TABLE_SUFFIX AS yyyymm,
  AVG(dcl.density) as average_dcl
FROM
  `chrome-ux-report.country_cl.*`, 
  UNNEST(dom_content_loaded.histogram.bin) as dcl
WHERE
  form_factor.name = 'desktop' 
GROUP BY
  yyyymm
ORDER BY
  yyyymm  

Кроме того, я хотел бы отметить, что в соответствии с документацией желательно избегать чрезмерного использования подстановочных знаков, выбирающих диапазоны дат и материализующих результаты больших наборов данных. Также я хотел бы отметить, что BigQuery ограничивает кэшированные результаты до 10 ГБ.

Надеюсь, это поможет.

1 голос
/ 21 января 2020

Позвольте мне начать говорить, что Тайм-аут запроса BigQuery очень длинный (6 часов), поэтому у вас не должно быть проблем на этом фронте, но вы можете столкнуться с другими ошибками.

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

Нашим решением было объединить всю эту таблицу в один столбец с добавлением столбца «страна» и использовать его в качестве столбца кластеризации. Это не только сделало наши запросы выполненными, но и сделало их даже быстрее, чем наше временное решение - выполнить тот же запрос для подмножества таблиц стран в качестве промежуточных шагов, а затем объединить результаты вместе. Теперь он стал быстрее, проще и чище.

Возвращаясь к заданному вами c вопросу, я предлагаю создать новую таблицу (в которой вам нужно будет разместить $$$), которая будет сочетать все таблицы внутри набора данных в виде многораздельной таблицы.

Самый быстрый способ, к сожалению, и более дорогой (вы заплатите за проверку запросов), состоит в использовании оператора create table.

create table `project_id.dataset_id.table_id`
partition by date_month
cluster by origin
as (
select
  date(PARSE_TIMESTAMP("%Y%m%d", concat(_table_suffix, "01"), "UTC")) as date_month,
  *
from `chrome-ux-report.country_cl.*`
);

Если этот запрос не удался, вы можете запустить его для поднабора таблиц, например, where starts_with(_table_suffix, '2018'), и выполнить следующий запрос с расположением 'write append' для таблицы, которую вы создали ранее.

select
  date(PARSE_TIMESTAMP("%Y%m%d", concat(_table_suffix, "01"), "UTC")) as date_month,
  *
from `chrome-ux-report.country_cl.*`
where starts_with(_table_suffix, '2019')

Если Вы заметили, что я также использовал столбец кластеризации, что, по-моему, является лучшим методом.

Примечание для тех, кто занимается Google publi c наборов данных .

It было бы неплохо иметь набор данных publi c "chrome_ux_report" с одной таблицей, разбитой по дате и сгруппированной по стране.

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