6小时后查询超时,如何优化?

Query times out after 6 hours, how to optimize it?

我有两个 table,shapessquares,我根据 GEOGRAHPY 列的交集加入。

shapestable包含车辆行驶路线:

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

我们在 ARRAY 中将 shape_lines 分开,因为形状有时会自行折回,我们希望将这些线段分开而不是

squares table 包含一个 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

这些形状代表车辆的行驶路线。对于每种形状,我们都在单独的 table 中计算了有害物质的排放量。目的是计算每个网格正方形的排放量,假设它们沿路线均匀分布。为此,我们需要知道路线形状的哪一部分与每个网格单元相交。

这是用于计算的查询:

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 无法处理的。

我考虑过 the geographic join optimizations 由 BigQuery 执行:

所以我认为 BigQuery 应该能够使用它使用的任何空间索引数据结构来优化此连接。

我也考虑过 advice about cross joins:

我怀疑 BigQuery 根据输入行数分配资源,而不是根据中间 table 或输出的大小。这可以解释我所看到的病态行为。

如何在合理的时间内进行此查询 运行?

下面肯定不适合评论格式所以我必须post这个作为答案...

我对你的查询做了三处调整

  • 使用 JOIN ... ON 而不是 CROSS JOIN ... WHERE
  • 注释掉square_portion计算
  • 使用目的地 table 和 Allow Large Results 选项

即使您预计输出只有 330 万行 - 实际上它大约是 6.6 B ( 6,591,549,944) 行 - 您可以在下面看到我的实验结果

注意有关计费层级的警告 - 因此您最好使用预留(如果可用)
显然,取消注释 square_portion 计算会增加插槽使用量 - 因此,您可能需要重新访问您的 requirements/expectations

我认为 squares 颠倒了,导致几乎完整的地球多边形:

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

打印像 5.1E14 这样的结果 - 这是整个地球区域。所以任何一条线几乎都与所有的正方形相交。有关详细信息,请参阅 BigQuery 文档: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)