雪花 ST_POLYGON(TO_GEOGRAPHY(...)) 效率低下

Snowflake ST_POLYGON(TO_GEOGRAPHY(...)) Is Inefficient

我有几个使用地理空间条件的查询。这些查询 运行 出奇地慢。最初我以为是地理空间计算本身,但把所有东西都剥离到 ST_POLYGON(TO_GEOGRAPHY(...)),它仍然很慢。如果每一行都有自己的多边形,这将是有意义的,但条件在查询中使用静态多边形:

SELECT 
    ST_POLYGON(TO_GEOGRAPHY('LINESTRING(-95.75122850074004 28.793166796020444,-95.68622920563344 30.207416499279063,-94.5162418937178 32.56537633083211,-90.94128066286225 34.24734047810797,-88.17881062083825 36.812423897251634,-86.13133282498448 38.15341651409619,-85.28634198860107 38.66275098353796,-84.37635185711038 38.789523129087826,-82.84886842210855 38.4848923369382,-82.32887406125734 37.820427257446994,-82.26387476615074 36.96838022284757,-82.03637723327772 36.00158943485101,-80.99638851157454 35.34155096040939,-78.52641529752944 34.62260477275565,-77.51892622337955 34.005211031324734,-78.26641811710381 31.1020568651834,-80.24889661785029 29.926151366059756,-83.59636031583283 28.793166796020444,-95.75122850074004 28.793166796020444)'))
FROM TABLE(GENERATOR(ROWCOUNT=>1000000))

Snowflake 应该能够弄清楚它只需要为整个查询计算一次这个多边形。然而,添加的行越多,速度就越慢。在 x-small 上,此查询需要一分钟多的时间。此查询的位置:

SELECT 
    'LINESTRING(-95.75122850074004 28.793166796020444,-95.68622920563344 30.207416499279063,-94.5162418937178 32.56537633083211,-90.94128066286225 34.24734047810797,-88.17881062083825 36.812423897251634,-86.13133282498448 38.15341651409619,-85.28634198860107 38.66275098353796,-84.37635185711038 38.789523129087826,-82.84886842210855 38.4848923369382,-82.32887406125734 37.820427257446994,-82.26387476615074 36.96838022284757,-82.03637723327772 36.00158943485101,-80.99638851157454 35.34155096040939,-78.52641529752944 34.62260477275565,-77.51892622337955 34.005211031324734,-78.26641811710381 31.1020568651834,-80.24889661785029 29.926151366059756,-83.59636031583283 28.793166796020444,-95.75122850074004 28.793166796020444)'
FROM TABLE(GENERATOR(ROWCOUNT=>3000000))

(增加了 2mm 行以匹配字节数)

可在 2 秒内完成。

我尝试用 WITH 语句自己“预计算”多边形,但 SF 发现 WITH 是多余的并将其删除。我也尝试设置一个会话变量,但是你不能将像这样的复杂值设置为变量。

我认为这是一个错误。

地理空间功能目前处于预览阶段,团队正在努力进行各种优化。

对于这种情况,我想指出将多边形设为单行 table 会有所帮助,但我仍然希望随着团队将此功能从测试版中获得更好的性能。

让我创建一个 table 一行,多边形:

create or replace temp table poly1
as
select ST_POLYGON(TO_GEOGRAPHY('LINESTRING(-95.75122850074004 28.793166796020444,-95.68622920563344 30.207416499279063,-94.5162418937178 32.56537633083211,-90.94128066286225 34.24734047810797,-88.17881062083825 36.812423897251634,-86.13133282498448 38.15341651409619,-85.28634198860107 38.66275098353796,-84.37635185711038 38.789523129087826,-82.84886842210855 38.4848923369382,-82.32887406125734 37.820427257446994,-82.26387476615074 36.96838022284757,-82.03637723327772 36.00158943485101,-80.99638851157454 35.34155096040939,-78.52641529752944 34.62260477275565,-77.51892622337955 34.005211031324734,-78.26641811710381 31.1020568651834,-80.24889661785029 29.926151366059756,-83.59636031583283 28.793166796020444,-95.75122850074004 28.793166796020444)'
       )) polygon
;

为了看看这是否有帮助,我尝试了 100 万行交叉连接:

select *
from poly1, TABLE(GENERATOR(ROWCOUNT=>1000000));

这需要 14 秒,在查询分析器中您可以看到大部分时间花在了内部 TO_OBJECT​(​GET_PATH​(​POLY1​.​POLYGON, '_shape'​)​​

有趣的是,前面的操作主要与多边形的 ascii 表示有关。 运行 对该多边形的操作要快得多:

select st_area(polygon)
from poly1, TABLE(GENERATOR(ROWCOUNT=>1000000));

这个查询应该花费更长的时间(查找多边形的面积听起来比仅仅选择它更复杂),但结果只用了 7 秒(~一半)。

感谢反馈,团队会继续优化此类案例


对于任何对问题中的特定多边形感到好奇的人 - 这是一颗善良的心: