Пространственная база данных, странное поведение индекса - PullRequest
0 голосов
/ 10 февраля 2011

Итак, в моей базе данных есть таблица с идентификатором типа BigInt и геометрией типа 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

Я получаю сообщение об ошибке:

Обработчик запросов не может произвести план запроса для запроса с подсказка пространственного индекса. Причина: Пространственная индексы не поддерживают сравнение поставляется в предикате. Пытаться удаление указателей или удаление SET FORCEPLAN.

Насколько мне известно, эти два запроса в основном эквивалентны. Может кто-нибудь объяснить, почему это происходит и как (или если) я могу заставить индекс работать со вторым запросом?

Спасибо

Редактировать: Только что заметил, что второе было = 0, а не = 1 в предложении where, кто-нибудь знает, почему индекс нельзя использовать с = 0? (2-й запрос работает с = 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: Я нашел решение для моей проблемы с левым соединением и нулевой проверкой, но мне все еще интересно, почему вы не можете использовать индекс на ложном пересечении, если кто-то может просветить мне

1 Ответ

1 голос
/ 25 февраля 2011

Нет технической причины, по которой пространственный индекс не может поддерживать этот запрос, однако сгенерированный план запроса по сути будет таким же, как если бы вы выполняли его самостоятельно с левым анти-полусоединением.Поддержка этого была рассмотрена, но это требует дополнительных изменений в оптимизаторе запросов, чтобы соответствовать этому предикату и генерировать правильный план запроса.

Таким образом, учитывая, что это не обычная форма запроса, и все еще относительно легко написать запрос для использования индекса самостоятельно, этот шаблон не был включен в список поддерживаемых предикатов для пространственногоиндексов.

...