我有两个表,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小时后超时,而不是产生有用的结果。
在最坏的情况下,查询可以生成66亿行,但在实践中不会发生这种情况。我估计每个形状通常相交可能50个网格方块,所以输出应该在65k * 50 = 3.3M行;没有什么是BigQuery无法处理的。
我已经考虑过由BigQuery执行的BigQuery:
WHERE
子句中两个带有谓词地理函数的表的联接。检查一下。我甚至将我的INNER JOIN
重写为上面所示的等效的“逗号”联接。
检查一下。shape_geography
和square_geography
都直接来自现有的表。
ST_Intersects
检查一下。只有一个ST_Intersect
调用,没有其他条件。
检查一下。这些情况都不适用。
因此,我认为BigQuery应该能够使用它使用的任何空间索引数据结构来优化这个连接。
我也考虑过关于交叉连接的建议
这个查询肯定会产生比输入更多的输出;这是它的本质,是无法避免的。
CROSS JOIN
时,预先聚合您的数据。
为了避免与连接相关的性能问题,这些连接会产生比输入更多的输出:- Use a GROUP BY clause to pre-aggregate the data.
检查一下。我已经预先聚合了按形状分组的排放数据,这样shapes
表中的每个形状都是唯一和不同的。
我认为这个查询不可能使用窗口函数。
我怀疑BigQuery根据输入行数分配资源,而不是根据中间表或输出的大小分配资源。这就解释了我所看到的病态行为。
如何使此查询在合理的时间内运行?
发布于 2020-02-12 22:44:32
我认为squares
被倒了,导致地球上几乎全部的多边形:
select st_area(square_geography), * from `open-transport-data.public.squares`
打印结果类似于5.1E14
-这是一个完整的地球仪区域。所以任何一条线都与几乎所有的正方形相交。详细信息请参见BigQuery文档:方向
您可以通过运行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)
发布于 2020-02-12 18:13:29
下面肯定不符合评论格式,所以我不得不把这个作为答复.
我对你的查询做了三次调整
square_portion
计算Allow Large Results
选项尽管您期望输出只有3.3M行--实际上它大约是6.6行(6,591,549,944行)--但您可以看到下面的实验结果
请注意有关收费层的警告-因此,如果有预订,您最好使用
显然,不注释square_portion
计算会增加插槽的使用,因此,您可能需要重新考虑您的需求/期望。
https://stackoverflow.com/questions/60183823
复制相似问题