Тайм-аут запроса через 6 часов, как его оптимизировать? - PullRequest
2 голосов
/ 12 февраля 2020

У меня есть две таблицы, shapes и squares, к которым я присоединяюсь на основе пересечений столбцов GEOGRAHPY.

Таблица shapes содержит маршруты движения транспортных средств:

shape_key        STRING            identifier for the shape
shape_lines      ARRAY<GEOGRAPHY>  consecutive line segments making up the shape
shape_geography  GEOGRAPHY         the union of all shape_lines
shape_length_km  FLOAT64           length of the shape in kilometers

Rows: 65k
Size: 718 MB

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

Таблица squares содержит сетку из квадратов 1 × 1 км:

square_key        INT64      identifier of the grid square
square_geography  GEOGRAPHY  four-cornered polygon describing the grid square

Rows: 102k
Size: 15 MB

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

Вот запрос для вычисления:

SELECT
  shape_key,
  square_key,
  SAFE_DIVIDE(
      (
        SELECT SUM(ST_LENGTH(ST_INTERSECTION(line, square_geography))) / 1000
        FROM UNNEST(shape_lines) AS line
      ),
      shape_length_km)
    AS square_portion
FROM
  shapes,
  squares
WHERE
  ST_INTERSECTS(shape_geography, square_geography)

К сожалению, этот запрос истекает через 6 часов вместо получения полезного результата.

В худшем случае запрос может выдать 6,6 миллиардов строк, но на практике этого не произойдет. Я полагаю, что каждая фигура обычно пересекает, может быть, 50 квадратов сетки, поэтому результат должен быть около 65k * 50 = 3,3M строк; ничего, с чем BigQuery не мог справиться.

Я рассмотрел географию c оптимизаций соединения , выполненных BigQuery:

  • Пространственные СОЕДИНЕНИЯ - это объединения двух таблиц с функцией предиката geographi c в предложении WHERE.

    Проверка. Я даже переписал INNER JOIN в эквивалентное объединение «запятая», показанное выше.

  • Пространственные объединения работают лучше, когда сохраняются ваши географические данные.

    проверка. И shape_geography, и square_geography взяты прямо из существующих таблиц.

  • BigQuery реализует оптимизированные пространственные соединения для операторов INNER JOIN и CROSS JOIN со следующими стандартными функциями предикатов SQL : [...] ST_Intersects

    Проверка. Просто один вызов ST_Intersect, никаких других условий.

  • Пространственные объединения не оптимизированы: для соединений LEFT, RIGHT или FULL OUTER; в случаях с участием ANTI; когда пространственный предикат отрицается.

    Проверка. Ни один из этих случаев не применим.

Поэтому я думаю, что BigQuery должен иметь возможность оптимизировать это объединение, используя любые структуры данных пространственной индексации, которые он использует.

Я также рассмотрел советы по перекрестным соединениям :

  • Избегайте объединений, которые генерируют больше выходных данных, чем входных.

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

  • Когда требуется CROSS JOIN, предварительно агрегируйте ваши данные.

    Чтобы избежать проблем с производительностью, связанных с объединения, которые генерируют больше выходных данных, чем входных данных:

    • Используйте предложение GROUP BY для предварительной агрегации данных.

    Проверка. Я уже предварительно агрегировал данные о выбросах, сгруппированные по фигурам, чтобы каждая фигура в таблице shapes была уникальной и уникальной.

    • Используйте оконную функцию. Оконные функции часто более эффективны, чем перекрестное соединение. Для получения дополнительной информации см. analyti c functions .

    Я не думаю, что можно использовать оконную функцию для этого запроса.

Я подозреваю, что BigQuery распределяет ресурсы на основе количества входных строк, а не размера промежуточных таблиц или выходных данных. Это объясняет патологическое поведение, которое я вижу.

Как я могу заставить этот запрос выполняться в разумные сроки?

Ответы [ 2 ]

1 голос
/ 13 февраля 2020

Я думаю, что squares было инвертировано, в результате чего были получены почти полные полигоны Земли:

select st_area(square_geography), * from   `open-transport-data.public.squares`

Печатает результаты наподобие 5.1E14 - это полная площадь земного шара. Таким образом, любая линия пересекает почти все квадраты. См. BigQuery do c для получения подробной информации: https://cloud.google.com/bigquery/docs/gis-data#polygon_orientation

Вы можете инвертировать их, запустив ST_GeogFromText(wkt, FALSE) - выбирает меньший многоугольник, игнорируя ориентацию многоугольника, это работает довольно быстро:

SELECT
  shape_key,
  square_key,
  SAFE_DIVIDE(
      (
        SELECT SUM(ST_LENGTH(ST_INTERSECTION(line, square_geography))) / 1000
        FROM UNNEST(shape_lines) AS line
      ),
      shape_length_km)
    AS square_portion
FROM
  `open-transport-data.public.shapes`,
  (select 
       square_key, 
       st_geogfromtext(st_astext(square_geography), FALSE) as square_geography,
     from `open-transport-data.public.squares`) squares
WHERE
  ST_INTERSECTS(shape_geography, square_geography)
1 голос
/ 12 февраля 2020

Ниже определенно не подходит формат комментариев, поэтому я должен опубликовать это как ответ ...

Я сделал три корректировки для вашего запроса

  • , используя JOIN ... ON вместо CROSS JOIN ... WHERE
  • комментирование square_portion вычисление
  • с использованием таблицы назначения с параметром Allow Large Results

Даже если вы ожидали всего 3,3 М строк в выводе - на самом деле это около 6,6 B (6 591 549 944) строк - вы можете увидеть результат моего эксперимента ниже

enter image description here

Обратите внимание на предупреждение о выставлении счетов Уровень - так что вам лучше использовать Бронирование, если доступно
Очевидно, что отмена комментариев square_portion вычисление увеличит использование слотов - поэтому вам, возможно, придется пересмотреть ваши требования / ожидания

...