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

Google bigquery 查询6小时后超时,如何优化?,google-bigquery,gis,cartesian-product,Google Bigquery,Gis,Cartesian Product,我有两个表,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 uni

我有两个表,
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
这些形状表示车辆的行驶路线。对于每种形状,我们在单独的表格中计算了有害物质的排放量。目的是计算每平方网格的排放量,假设排放量沿路线均匀分布。为此,我们需要知道管线形状的哪个部分与每个网格单元相交

下面是计算该值的查询:

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执行:

  • 空间联接是在
    WHERE
    子句中具有谓词地理函数的两个表的联接

    检查。我甚至将我的
    内部连接
    重写为上面所示的等效“逗号”连接

  • 当地理数据被持久化时,空间连接的性能会更好

    检查。
    shape\u geography
    square\u geography
    都直接来自现有的表格

  • BigQuery使用以下标准SQL谓词函数为内部联接和交叉联接运算符实现优化的空间联接:[……]
    ST_Intersects

    检查。只需一次
    ST_Intersect
    调用,无其他条件

  • 空间连接未优化:用于左、右或完全外部连接;涉及反加入的案件;当空间谓词被否定时

    检查。这些情况都不适用

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

我亦考虑过:

  • 避免产生比输入更多输出的联接

    这个查询肯定会产生比输入更多的输出;这是它的本质,无法避免

  • 当需要交叉联接时,请预先聚合数据

    要避免与生成的输出多于输入的联接相关的性能问题,请执行以下操作:

    • 使用GROUPBY子句预聚合数据
    检查。我已经预先汇总了按形状分组的排放数据,因此
    shapes
    表中的每个形状都是唯一和不同的

    • 使用窗口功能。窗口函数通常比使用交叉联接更有效。有关详细信息,请参阅
    我认为这个查询不可能使用窗口函数

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


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

下面的注释格式肯定不适合,因此我必须将此作为答案发布

我对你的问题做了三个调整

  • 正在使用连接。。。在上而不是交叉连接。。。在哪里
  • 注释掉
    平方部分
    计算
  • 将目标表与
    允许大结果
    选项一起使用
尽管您预期的输出只有330万行—实际上大约是6.6B(6591549944)行—但您可以在下面看到我的实验结果

请注意有关计费层的警告-因此,如果可用,您最好使用预订

显然,取消注释
square\u部分
计算将增加插槽使用率-因此,您可能需要重新审视您的要求/期望

我认为
正方形
被颠倒了,导致几乎全地球多边形:

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)

你能提供这些表格的样本吗?我想复制it@rmesteves非常感谢。我已经授予
bigquery.dataViewer
访问
alluser
,希望这就足够了。表的名称是
开放式传输数据.public.shapes
开放式传输数据.public.squares
。逗号是
交叉连接
-这可能会破坏您的query@MartinWeitzmann当然是交叉连接。就像我说的,这是野兽的本性。谢谢你的彻底调查!6.6B输出行意味着我们得到了完整的笛卡尔积。。。那不是我的本意。明天我会仔细看看数据。是的,就是这样,非常感谢!我现在要对QGIS说一些严厉的话,因为这些正方形来自的CSV with WKT导出似乎包含右手多边形,即使WKT应该使用左手规则。
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)