空间数据库,奇怪的索引行为

发布于 2024-10-17 02:40:09 字数 2060 浏览 3 评论 0原文

因此,我的数据库有一个表,其 Id 类型为 BigInt,Geometry 类型为 Geometry。 Geometry 字段有一个名为 idx_Geometry 的空间索引

以下查询使用该索引按预期工作:

DECLARE @Geometry geometry
SET @Geometry = geometry::Parse('Polygon((300000 300000, 300000 325000, 325000 325000, 325000 300000, 300000 300000))')
SELECT Id FROM [Database].[dbo].[Table] WITH(index(idx_Geometry)) WHERE Geometry.STIntersects(@Geometry) = 1

但是,当我尝试该查询时,

DECLARE @Geometry geometry
SET @Geometry = geometry::Parse('Polygon((300000 300000, 300000 325000, 325000 325000, 325000 300000, 300000 300000))')
SELECT a.Id FROM [Database].[dbo].[Table] a with(Index(idx_Geometry)) WHERE a.Geometry.STIntersects(@Geometry) = 0

我收到错误消息:

查询处理器无法生成 查询的查询计划 空间索引提示。原因:空间 索引不支持比较数 在谓词中提供。尝试 删除索引提示或删除 设置部队计划。

就我而言,这两个查询基本上是等效的。谁能解释为什么会发生这种情况以及我如何(或是否)可以让索引与第二个查询一起使用?

谢谢

编辑:刚刚注意到where子句中的第二个是= 0,而不是= 1,有人知道为什么索引不能与= 0一起使用吗? (第二个查询适用于= 1)

编辑2:只是更新什么有效和什么无效

DECLARE @Geometry geometry
SET @Geometry = geometry::Parse('Polygon((300000 300000, 300000 325000, 325000 325000, 325000 300000, 300000 300000))')

--Works
SELECT Id FROM [RoadRoutingDatabase].[dbo].[Node] WITH(index(idx_Geometry)) WHERE Geometry.STIntersects(@Geometry) = 1
SELECT a.Id FROM [RoadRoutingDatabase].[dbo].[Node] a with(Index(idx_Geometry)) WHERE a.Geometry.STIntersects(@Geometry) = 1 

--Gives Error Message
SELECT Id FROM [RoadRoutingDatabase].[dbo].[Node] WITH(index(idx_Geometry)) WHERE Geometry.STIntersects(@Geometry) = 0
SELECT a.Id FROM [RoadRoutingDatabase].[dbo].[Node] a with(Index(idx_Geometry)) WHERE a.Geometry.STIntersects(@Geometry) = 0

--Works but doesn't use Index
SELECT Id FROM [RoadRoutingDatabase].[dbo].[Node] WHERE Geometry.STIntersects(@Geometry) = 0
SELECT a.Id FROM [RoadRoutingDatabase].[dbo].[Node] a WHERE a.Geometry.STIntersects(@Geometry) = 0 

编辑3:我已经找到了解决我的问题的方法左连接和空检查,但我仍然很好奇为什么不能在假相交上使用索引,如果有人可以启发我

So, my database has a Table with a Id of type BigInt and a Geometry of type Geometry. The Geometry field has a spatial index called idx_Geometry

The following query works as expected using the index:

DECLARE @Geometry geometry
SET @Geometry = geometry::Parse('Polygon((300000 300000, 300000 325000, 325000 325000, 325000 300000, 300000 300000))')
SELECT Id FROM [Database].[dbo].[Table] WITH(index(idx_Geometry)) WHERE Geometry.STIntersects(@Geometry) = 1

However when I try the query

DECLARE @Geometry geometry
SET @Geometry = geometry::Parse('Polygon((300000 300000, 300000 325000, 325000 325000, 325000 300000, 300000 300000))')
SELECT a.Id FROM [Database].[dbo].[Table] a with(Index(idx_Geometry)) WHERE a.Geometry.STIntersects(@Geometry) = 0

I get the error message:

The query processor could not produce
a query plan for a query with a
spatial index hint. Reason: Spatial
indexes do not support the comparand
supplied in the predicate. Try
removing the index hints or removing
SET FORCEPLAN.

As far as I'm concerned those two queries are basically equivalent. Can anyone explain why this is happening and how (or if) I can get the index to work with the second query?

Thanks

Edit: Just noticed the second one was = 0, not =1 in the where clause, anyone know why the index can't be used with = 0? (the 2nd query works with = 1)

Edit 2: Just a update of what works and what doesn't

DECLARE @Geometry geometry
SET @Geometry = geometry::Parse('Polygon((300000 300000, 300000 325000, 325000 325000, 325000 300000, 300000 300000))')

--Works
SELECT Id FROM [RoadRoutingDatabase].[dbo].[Node] WITH(index(idx_Geometry)) WHERE Geometry.STIntersects(@Geometry) = 1
SELECT a.Id FROM [RoadRoutingDatabase].[dbo].[Node] a with(Index(idx_Geometry)) WHERE a.Geometry.STIntersects(@Geometry) = 1 

--Gives Error Message
SELECT Id FROM [RoadRoutingDatabase].[dbo].[Node] WITH(index(idx_Geometry)) WHERE Geometry.STIntersects(@Geometry) = 0
SELECT a.Id FROM [RoadRoutingDatabase].[dbo].[Node] a with(Index(idx_Geometry)) WHERE a.Geometry.STIntersects(@Geometry) = 0

--Works but doesn't use Index
SELECT Id FROM [RoadRoutingDatabase].[dbo].[Node] WHERE Geometry.STIntersects(@Geometry) = 0
SELECT a.Id FROM [RoadRoutingDatabase].[dbo].[Node] a WHERE a.Geometry.STIntersects(@Geometry) = 0 

Edit 3: I have found a work around for my issue with a left join and null check but I am still curious about why you can't use a index on a false intersect if anyone can enlighten me

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

追风人 2024-10-24 02:40:09

没有技术原因空间索引无法支持此查询,但是生成的查询计划本质上与您自己使用左反半连接执行的查询计划相同。考虑过支持这一点,但这样做需要对查询优化器进行额外的更改,以便匹配该谓词并生成正确的查询计划。

因此,鉴于这不是常见的查询形状,并且自己编写查询来使用索引仍然相对容易,因此该模式未包含在 空间索引支持的谓词列表

There is no technical reason the spatial index could not support this query, however the query plan generated would be essentially the same as doing it yourself with a left anti semi join. Supporting this was considered, but doing so involves additional changes to the Query Optimizer in order to match this predicate and generate the correct query plan.

So given this is not a common query shape and it is still relatively easy to write the query to use the index yourself, this pattern was not included in the list of supported predicates for spatial indexes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文