&& vs ST_Intersects 性能

yur*_*sen 3 postgresql spatial postgis

我试图找出位于矩形区域(信封)内的点。我在使用了一点点难度的理解性能影响&&运营商相比ST_Intersect

但是,我想我在尝试提出我的问题时解释了我自己的问题。我无论如何都会提交它,以防它对某人有用。

&&的手册说(具有讽刺意味的是,页面名称是 geometry_overlaps.html):

&& — 如果 A 的 2D 边界框与 B 的 2D 边界框相交,则返回 TRUE。`

ST_Intersects的手册说:

如果几何/地理“在二维空间上相交”-(共享空间的任何部分),则返回 TRUE,如果不相交(它们不相交),则返回 FALSE。对于地理 - 容差为 0.00001 米(因此任何靠近的点都被视为相交)

ST_Intersects在这种情况下将返回 true。因为我&&在任何一种情况下都使用矩形边界框,所以我的目标运算符几乎做同样的事情。我想知道是否&&是我的目的最快的运营商?感觉&&必须做更少的检查,所以它必须更有效率。

这是一个直接复制自&&,ST_Intersects改编的示例:

SELECT
        t1.id AS t1,
        t2.id AS t2,
        t1.ln && t2.ln AS "&&",
        ST_Intersects(t1.ln,t2.ln)
FROM ( VALUES
        (1, 'LINESTRING(0 0, 3 3)'::geometry),
        (2, 'LINESTRING(0 1, 0 5)'::geometry)
) AS t1(id,ln)
CROSS JOIN (VALUES
        (3, 'LINESTRING(1 2, 4 6)'::geometry)
) AS t2(id,ln);

 t1 | t2 | && | st_intersects 
----+----+----+---------------
  1 |  3 | t  | f
  2 |  3 | f  | f
(2 rows)
Run Code Online (Sandbox Code Playgroud)

下面是这些线应该是什么样子的简单图表。我刚刚添加了 plotted 以查看边界框如何完全适用于线条。为了我的目的,点总是在盒子里(虽然这个线的例子并没有真正反映我想要做的事情,但很好地说明)

在此处输入图片说明

问题 1 是 if在查找矩形边界框内的点时&&ST_Intersects使用 with ST_MakeEnvelope(矩形边界)快得多。

问题 2 也是我的理解是否正确,当检查矩形边界内的点时,&&ST_Intersects?

Eva*_*oll 6

背景、功能和性能

&& 操作员

&&是边界框重叠。所有操作符都调用 PostgreSQL 中的函数:\doS+ &&在这种情况下,您可以看到这个&&字面意思是调用 PostGIS 函数geometry_overlaps。这里唯一的问题是&&将使用来自文档的索引

通常,您需要使用“相交运算符” ( &&) 来测试要素的边界框是否相交。&& 运算符有用的原因是,如果空间索引可用于加速测试,则&&运算符将利用它。这可以使查询更快。

您可以在定义中geometry_overlaps看到它调用了一个内部 C 函数gserialized_overlaps_2d。该函数gserialized_overlaps_2d使用 4 次比较来确定边界框中是否存在重叠。除了增加选择性之外,这通常不是那么有用,因此您通常不想要它。

这意味着这不是一个性能问题, &&只是没有多大作用。然而,&&可以使用 GIST 索引做什么。

ST_Intersects

ST_Intersects 从文档中,

此函数调用将自动包含一个边界框比较,它将利用几何上可用的任何索引。

原因很简单,只有边界框使用索引。这意味着它会做&&其他事情。你可以看到\dfS+ st_intersects

SELECT $1 && $2 AND _ST_Intersects($1,$2);
Run Code Online (Sandbox Code Playgroud)

因此,它所做的额外位是根据您选择的后端调用geos_intersectssfcgal_intersects相交。在最好的情况下,你得到了geos_intersects,你可以在这里看到它的作用

从本质上讲,它告诉您是否有任何点相交而不做任何假设(浮点数学除外)。

混合 SRID

最后一点,值得注意的是,这两个操作以不同的方式处理混合 SRID。

你的问题

问题 1 是在查找矩形边界框内的点时,if&&ST_Intersects使用 ST_MakeEnvelope(矩形边界)时快得多。

是的,它更快 - 显着。它做得更少。除非一侧是一个简单的点,否则它不会在矩形边界框内找到“点”。除此之外,它会发现边界框重叠,如果所有点都位于边界框之外,则会出现误报。

问题 2 也是我的理解是否正确,当检查矩形边界内的点时,&&ST_Intersects?

不,现在应该清楚为什么了。