У меня есть две таблицы, 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 распределяет ресурсы на основе количества входных строк, а не размера промежуточных таблиц или выходных данных. Это объясняет патологическое поведение, которое я вижу.
Как я могу заставить этот запрос выполняться в разумные сроки?