Как я могу ускорить этот пространственный запрос Sql Server?

У меня есть (что я думаю) простой пространственный запрос Sql Server:

Захватите все штаты США, которые существуют внутри какого-либо 4-стороннего многоугольника (т. е. окна просмотра/ограничивающей рамки карты google/bing веб-страницы)

SELECT CAST(2 AS TINYINT) AS LocationType, a.Name AS FullName, 
    StateId, a.Name, Boundary.STAsText() AS Boundary, 
    CentrePoint.STAsText() AS CentrePoint
FROM [dbo].[States] a
WHERE @BoundingBox.STIntersects(a.Boundary) = 1

Запуск занимает 6 секунд :(

Вот план выполнения....

Удалено

А статистика работы фильтра...

Удалено

Теперь я просто не знаю, как это отладить ... чтобы выяснить, что мне нужно для точной настройки и т. Д. Есть ли у меня какие-либо пространственные индексы? Я так считаю ...

/****** Object:  Index [SPATIAL_States_Boundary]    
        Script Date: 07/28/2010 18:03:17 ******/
CREATE SPATIAL INDEX [SPATIAL_States_Boundary] ON [dbo].[States] 
(
    [Boundary]
)USING  GEOGRAPHY_GRID 
WITH (
    GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH), 
    CELLS_PER_OBJECT = 1024, PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF, 
    DROP_EXISTING = OFF, ALLOW_ROW_LOCKS  = ON, 
    ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

Нужно ли мне предоставлять дополнительную информацию о возвращаемых данных GEOGRAPHY? например. количество баллов и т.д.? Или мне нужно запустить profiler и вывести оттуда статистику?

Или мои Cells_per_object / Grids установлены неправильно (я действительно понятия не имею, что мне следует устанавливать для этих значений, TBH).

Кто-нибудь может помочь? Пожалуйста?

ОБНОВЛЕНИЕ/РЕДАКТИРОВАТЬ:

После первого ответа @Bobs ниже, подтверждающего, что пространственный индекс не используется, потому что первичный ключ (кластеризованный индекс) будет быстрее, чем некластеризованный индекс в таблице с 50 нечетными строками... Затем я попытался принудительно Пространственный индекс (для дерьма и хихиканья): -

SELECT CAST(2 AS TINYINT) AS LocationType, a.Name AS FullName, 
    StateId, a.Name, Boundary.STAsText() AS Boundary, 
    CentrePoint.STAsText() AS CentrePoint
FROM [dbo].[States] a WITH (INDEX(SPATIAL_States_Boundary))
WHERE @BoundingBox.STIntersects(a.Boundary) = 1

... и угадайте, что... запрос выполняется мгновенно.

ВТФ? Кто-нибудь еще знает, почему? Нужно ли мне опубликовать план запроса для этого, чтобы помочь объяснить, почему/что?


person Pure.Krome    schedule 28.07.2010    source источник


Ответы (2)


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

Запрос выполняет сканирование кластеризованного индекса по индексу PK_States. Он не использует пространственный индекс. Это связано с тем, что оптимизатор запросов считает, что будет лучше использовать кластеризованный индекс вместо любого другого индекса. Почему? Вероятно, потому, что в таблице «Штаты» мало строк (50 плюс, может быть, еще несколько для Вашингтона, округ Колумбия, Пуэрто-Рико и т. д.).

SQL Server хранит и извлекает данные на страницах размером 8 КБ. Размер строки (см. раздел Оценка размера строки) для операции фильтрации составляет 8052 байта, что означает, что на страницу приходится одна строка, а во всей таблице около 50 страниц. План запроса оценивает, что он будет обрабатывать около 18 из этих строк (см. Оценочное количество строк). Это незначительное количество строк для обработки. Мое объяснение не касается дополнительных страниц, которые являются частью таблицы, но дело в том, что это число составляет около 50, а не 50 000 страниц.

Итак, вернемся к тому, почему он использует индекс PK_States вместо индекса SPATIAL_States_Boundry. Кластеризованный индекс по определению содержит фактические данные для таблицы. Некластеризованный индекс указывает на страницу, на которой существуют данные, поэтому нужно получить больше страниц. Таким образом, некластеризованный индекс становится полезным только при наличии больших объемов данных.

Возможно, вы можете что-то сделать, чтобы уменьшить количество обрабатываемых страниц (например, использовать покрывающий индекс), но ваш текущий запрос уже хорошо оптимизирован, и вы не увидите значительного повышения производительности.

person bobs    schedule 28.07.2010
comment
Cпасибо за подробный ответ. Я действительно очень-очень это оценил :) Еще несколько вопросов: если оптимизатор запросов решит использовать Clustered Index - kewl. И вы правы... в этой таблице всего около 56 строк. Так почему же это займет так много времени? есть ли что-то еще, где я могу увидеть, где снижается пропускная способность :( Если это не запрос ... что еще это может быть? (сервер не работает на 100%, кстати). - person Pure.Krome; 29.07.2010
comment
я также обновил начальный пост дополнительной информацией .. внизу в разделе EDIT/UPDATE. Пожалуйста, можно перечитать? - person Pure.Krome; 29.07.2010
comment
Очень интересно, что пространственный индекс так хорошо работает. Я подозреваю, что производительность для оценки пространственного состояния с помощью кластеризованного индекса не так высока, как при использовании пространственного индекса. В целях тестирования вы можете попробовать некластеризованный индекс для непространственного столбца и выполнить запрос, использующий этот столбец. Затем посмотрите, как запрос сравнивается с вашими предыдущими запросами. Было бы интересно посмотреть, как работает запрос без пространственной логики. - person bobs; 29.07.2010

Попробуйте это без подсказки индекса:

EXEC sp_executesql N'
  SELECT CAST(2 AS TINYINT) AS LocationType, a.Name AS FullName, 
      StateId, a.Name, Boundary.STAsText() AS Boundary, 
      CentrePoint.STAsText() AS CentrePoint
  FROM [dbo].[States] a
  WHERE @BoundingBox.STIntersects(a.Boundary) = 1'
, N'@BoundingBox GEOGRAPHY', @BoundingBox

Если это имеет значение, см. раздел здесь для более подробной информации:

Если вы запускаете код в SSMS, используйте sp_executesql для пространственного запроса (или используйте собственную хранимую процедуру с пространственным значением в качестве параметра), чтобы гарантировать, что стоимость запроса «знает» значение параметра во время создания плана запроса. , то есть в начале пакета или при входе в хранимую процедуру или sp_executesql.

person Peter Radocchia    schedule 05.09.2010
comment
интересно ... Итак, я переместил его в хранимую процедуру с передачей переменной boundingBox. Теперь 9 секунд без использования INDEX. Это на SQL 2008 R2/10.50 RTM. - person Pure.Krome; 05.09.2010
comment
кроме того, запуск его (как указано выше) в SSMS возвращает результат через 9 секунд без использования индекса, и помещение этого кода выше в хранимую процедуру с переданной переменной BoundingBox снова делает то же самое. :( - person Pure.Krome; 05.09.2010
comment
Это довольно забавно. Вы также можете поиграть с w./ .Filter(), если вы еще этого не сделали. Я часто обнаруживаю, что материализую результаты .Filter() во временной таблице, а затем выполняю более точные операции с ней. - person Peter Radocchia; 05.09.2010
comment
Кроме того, я рекомендую размещать перекрестные сообщения на social.msdn.microsoft.com/Forums/ en-US/sqlspatial. Читатели там намного лучше, чем SO для пространственных вопросов SQL Server. - person Peter Radocchia; 05.09.2010