将算法打包到 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
)
我注意到 运行 在 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
)