BigQuery — увеличенное время обработки с определенной таблицей

#google-bigquery

# #google-bigquery

Вопрос:

Мы выполнили 2 запроса к 2 разным парам таблиц (несколько объединений для получения обновленных данных и прочего), с одинаковым (как для таблицы, так и для запроса) форматом и целью. Разница между запросами заключается в строковой переменной, содержащейся в строке REGEXP_MATCH (формулы регулярных выражений имеют один и тот же формат, просто другая базовая строка). Остальное точно такое же, за исключением, конечно, содержащихся данных.

Несмотря на то, что запрос обрабатывал почти 2 ГБ данных за 20-50 секунд для одной пары таблиц, тот же запрос с другим параметром регулярного ВЫРАЖЕНИЯ (тот же столбец) обрабатывает для другой пары таблиц 250 МБ за 100 секунд (иногда даже от 500 до 1000 секунд). Оба запроса выполняются в интерактивном режиме, без кэширования результатов.

Что может быть причиной этого и есть ли исправление?

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

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

  • Выполнение действий «готово» — получение пользователей из обновленных событий, выбранных первым регулярным выражением
  • Получить действия «не должно быть сделано» — получить пользователей из обновленных событий, выбранных вторым событием.
  • Создайте разницу между 2 с помощью LEFT OUTER JOIN
  • Объединение выбранных пользователей с таблицей ПОЛЬЗОВАТЕЛЕЙ (также получение обновленных пользователей)

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

 SELECT Count(*) as count
FROM 
    (
    SELECT final._nid as _nid
    FROM (
        -- Start of events funnel
        SELECT did.user as user
        FROM (
            -- Get updated events
            SELECT events.user as user, events.createdOn as createdOn
            FROM [shop1_events] as events
            JOIN EACH (
                SELECT session, createdOn, MAX(updatedOn) as updatedOn
                FROM [shop1_events]
                GROUP EACH BY session, createdOn) as latest_events
            ON events.session = latest_events.session AND events.createdOn = latest_events.createdOn AND events.updatedOn = latest_events.updatedOn
            -- Regex for categories (concatenated categories)
            WHERE ((REGEXP_MATCH(events.category_a , r"([:^]100000453[:^]|^100000453$|^100000453[^:]|[^:]100000453$)"))) AND events.type = 10006) as did
        -- Exclude the following events:    
        LEFT OUTER JOIN EACH (
            -- Get updated events
            SELECT events.user as user, events.createdOn as createdOn
            FROM [shop1_events] as events
            JOIN EACH (
                SELECT session, createdOn, MAX(updatedOn) as updatedOn
                FROM [shop1_events]
                GROUP EACH BY session, createdOn) as latest_events
            ON events.session = latest_events.session AND events.createdOn = latest_events.createdOn AND events.updatedOn = latest_events.updatedOn
            -- Regex for categories
            WHERE ((REGEXP_MATCH(events.category_a , r"([:^]100000485[:^]|^100000485$|^100000485[^:]|[^:]100000485$)"))) AND events.type = 10006) as step_not_0
        ON did.user = step_not_0.user
        WHERE step_not_0.user IS NULL) as funnel
    JOIN EACH (
        -- Join with users
        SELECT all._nid as _nid
        FROM [shop1_users] as all
        JOIN EACH (
            -- Get updated users
            SELECT _nid, MAX(updatedOn) as updatedOn
            FROM [shop1_users]
            GROUP EACH BY _nid) as latest
        ON all._nid = latest._nid AND all.updatedOn = latest.updatedOn
        ) as final
ON final._nid = funnel.user
GROUP EACH BY _nid) as counting;
 

Комментарии:

1. Добавьте запрос и — или, по крайней мере, — регулярное выражение.

2. Добавлены сведения о проблеме 🙂

3. Я думаю, что если разница в двух тестах — это только и только строка регулярного выражения. Тогда, возможно, вам не нужно предоставлять всю остальную информацию для вашей конкретной настройки, чтобы получить лучшие ответы. Каковы две строки регулярных выражений в двух отдельных запросах, которые вызывают задержку? Я вижу две строки в вашем коде, но они находятся под одним и тем же запросом.

4. Дело в том, что я не уверен, что регулярное выражение является проблемой, поскольку таблицы, по которым выполняется запрос, также различны. Регулярными выражениями являются следующие: ([:^]<category>[:^]|^<category>$|^<category>[^:]|[^:]<category>$) Параметр <категория> также отличается для 2 таблиц. Кроме того, простые запросы иногда имеют непропорционально большое время обработки (значительно больше времени для таблицы меньшего размера).

5. В BigQuery теперь появилась новая функция под названием «Объяснение». Запустите оба ваших запроса и проанализируйте результаты, используя объяснение, чтобы лучше понять, почему они так сильно отличаются. Если это не поможет, возьмите идентификаторы вакансий и разместите их здесь. Тогда кто-нибудь из команды разработчиков BigQuery должен иметь возможность взглянуть.

Ответ №1:

Возможно, это помогает:

Вместо выполнения регулярного выражения, возможно, вы можете извлечь значение, которое имеет значение, и сравнить его с вашим:

Пример:

замените это

 REGEXP_MATCH(events.category_a , r"([:^]100000485[:^]|^100000485$|^100000485[^:]|[^:]100000485$)"))) 
 

для этого:

 REGEXP_REPLACE(events.category_a, r"D*(d )D*", (1)) = "100000485"
 

Комментарии:

1. Я ценю ваш ответ, но это только заставляет меня чувствовать, что я неправильно сформулировал свой вопрос. Короткая перефразировка моей проблемы: как возможно, чтобы для таблицы меньшего размера требовалось значительное время обработки по сравнению со значительно большей таблицей, учитывая, что выполняемые запросы в основном одинаковы?

2. @AlinLacea, ну, я не слишком много объяснял, но регулярные выражения могут занимать столько времени, в зависимости от обрабатываемых данных и эффективности. Я не уверен, была ли это проблема с вашим запросом, это был всего лишь самый простой способ дать вам подсказку по его улучшению.

Ответ №2:

Объем обрабатываемых данных показывает только, сколько данных считывается на первом этапе. Однако стоимость запроса может быть напрямую не связана с этим. Например, предложения JOIN или WHERE могут исключить большинство записей в одном случае из-за отсутствия совпадений, но оставить записи в другом случае. Или, может быть, есть некоторый перекос (конкретный ключ соединения, который встречается часто) в одной таблице, что приводит к замедлению выполнения запроса. Существует множество переменных, влияющих на производительность.

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

PS Запрос также может выиграть от небольшой перезаписи, называемой filter push down:

     SELECT events.user as user, events.createdOn as createdOn
    FROM [shop1_events] as events
    JOIN EACH (...) as latest_events
    ON ...
    WHERE <condition-for-events-table>
 

В

     SELECT events.user as user, events.createdOn as createdOn
    FROM (SELECT <fields-used> FROM [shop1_events] 
          WHERE <condition-for-events-table>) as events
    JOIN EACH (...) as latest_events
    ON ...