将算法打包到 Bigquery SQL UDF 时,如何避免性能急剧下降?

How can I avoid drastic decrease in performance when packaging algorithms into a Bigquery SQL UDFs?

我注意到 运行 在 Bigquery UDF 中 运行 比直接 运行 时相同的算法可能需要更长的时间(最多 x60)。

下面的两个代码片段说明了问题:

第一个在 1.6 秒内完成

WITH T_ AS (
    SELECT road_geom g
    FROM `bigquery-public-data.geo_us_roads.all_roads_04`
    ORDER BY ST_LENGTH(road_geom) desc
    LIMIT 1
  ),
  T0 AS (
    SELECT ST_PointN(g,idx) point, idx
    FROM T_, UNNEST(GENERATE_ARRAY(1, ST_NPOINTS(g))) AS idx
  )
SELECT point
FROM T0
ORDER BY ST_LENGTH(ST_MAKELINE(ARRAY_AGG(point) OVER ( ORDER BY idx ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING))) DESC
LIMIT 1

第二个用了 1 分 47 秒

CREATE TEMP FUNCTION
  myfunction(g GEOGRAPHY) AS ((
    WITH
        T0 AS (
    SELECT ST_PointN(g,idx) point, idx
    FROM UNNEST(GENERATE_ARRAY(1, ST_NPOINTS(g))) AS idx
  )
SELECT point
FROM T0
ORDER BY ST_LENGTH(ST_MAKELINE(ARRAY_AGG(point) OVER ( ORDER BY idx ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING))) DESC
LIMIT 1));
      
      
SELECT myfunction(road_geom)
FROM `bigquery-public-data.geo_us_roads.all_roads_04`
ORDER BY ST_LENGTH(road_geom) DESC
LIMIT 1

这些查询似乎有些不同。

首先通过最长的路计算T_中的单行,然后在T0计算中使用它来提取点列表,然后计算最长的线段。

第二个计算每条路,然后才通过最长的路得到一个结果。我猜优化器不够聪明,无法重写第二个查询。

我建议将最后一个查询编写如下,这样速度同样快:

SELECT myfunction(road_geom)
FROM (
    SELECT * 
    FROM `bigquery-public-data.geo_us_roads.all_roads_04`
    ORDER BY ST_LENGTH(road_geom) DESC
    LIMIT 1
)