2016-07-14 5 views
2

У меня есть таблица Точки с столбцом Точка типа ГЕОГРАФИЯ. Я бегу этот код, чтобы получить ближайший пункт:выбрать ближайшую точку sql сервер пространственный

DECLARE @Wgs84Longitude FLOAT; 
DECLARE @Wgs84Latitude FLOAT; 

DECLARE @Point GEOGRAPHY = Geography::STPointFromText(N'POINT(' 
              + CAST(@Wgs84Longitude AS NVARCHAR(MAX)) 
              + N' ' 
              + CAST(@Wgs84Latitude AS NVARCHAR(MAX)) 
              + N')', 4326); 

SELECT 
    TOP 1 
    * 
FROM Points 
ORDER BY @Point.STDistance(Point) ASC; 

Таблица Очки имеет этот индекс:

CREATE SPATIAL INDEX SpatialIndex ON Points (Point); 

К сожалению, запрос является довольно медленным. Есть ли что-то, что я могу улучшить, чтобы сделать его быстрее (индекс и/или запрос мудрым)?

PS:

Я также играл с некоторыми ароматами это:

CREATE SPATIAL INDEX SpatialIndex ON [Core].[InternationalPostcodeList](Point) 
USING GEOGRAPHY_GRID 
WITH 
(
--BOUNDING_BOX =(-8.164229, 49.18581, 8.05384, 60.717093) 
     GRIDS=(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH) 
    , CELLS_PER_OBJECT = 64 
    , PAD_INDEX = OFF 
    , SORT_IN_TEMPDB = OFF 
    , DROP_EXISTING = OFF 
    , ALLOW_ROW_LOCKS = ON 
    , ALLOW_PAGE_LOCKS = ON 
) ON [PRIMARY]; 

Производительность по-прежнему неприемлемо.

ответ

0

В статье Microsoft, посвященной MSDN, предлагается несколько улучшений, которые можно было бы сделать для обеспечения запроса «Самый близкий сосед» с использованием Пространственного индекса. Главный из них для меня - отсутствие использования STDistance в предложении WHERE для ограничения расстояния (без которого он никак не может фильтровать).

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

MSDN Nearest Neighbor

EDIT

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

DECLARE @Point GEOGRAPHY = GEOGRAPHY::Point(@latitude, @longitude, @srid); 

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

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

SELECT TOP 1 
* 
FROM 
Points P 
WHERE P.Point.STDistance(@Point) < (50 * 1609.344) -- 50 miles 
ORDER BY P.Point.STDistance(@Point) 

Мои результаты были значительно быстрее, чем 1 секунда. Если я опустил предложение WHERE, времена были примерно на 1500% медленнее (увеличится/уменьшится с размером набора данных). Но это было намного быстрее, чем ваши результаты за 10-12 секунд.

Вы можете проверить, работает ли ваш пространственный указатель? Если нет, попробуйте использовать подсказку WITH (INDEX (SpatialIndex)). Если это все еще не работает, можете ли вы загрузить план выполнения запроса?

+0

Спасибо. Когда я ввожу предложение WHERE, как это предлагается в статье, чтобы явно использовать использование пространственного индекса, запрос выполняется еще медленнее. – cs0815

+0

@csetzkorn Каков размер таблицы (в строках) и какие времена вы получаете в настоящее время? –

+0

Около 2,5 миллионов строк ... – cs0815