2016-08-02 4 views
0

Есть ли возможный способ улучшить ниже запрос:SQL Server География

DECLARE @radiusInMeters FLOAT = 400; 
DECLARE @dgeog geography = geography::Point(given_latitude, given_longitude, 4326).STBuffer(@radiusInMeters); 

select [fdx].latitude, [fdx].longitude 
from [dbo].[fdx] 
where @dgeog.STIntersects(geography::STGeomFromText('POINT(' + convert(varchar(20), [fdx].longitude) + ' ' + convert(varchar(20), [fdx].latitude) + ')', 4326) 
         ) = 1 
+3

Улучшите, каким образом? –

+1

Ваш запрос не использует пространственный указатель, а таблица не имеет столбца геометрии. Таким образом, время выполнения запросов слишком велико. –

+0

Мой вопрос был несколько обманчивым. Простите за это. В моей таблице есть столбец географии и пространственный индекс. Однако пространственный индекс не фигурировал в плане выполнения. Возможно, это связано с тем, как было создано поле географии. – ancdev

ответ

3

kcung и Хасан BINBOGA правильно, вам нужен пространственный индекс.

Посмотрите на ваш запрос: @ dgeog.STIntersects (xxxx) = 1 Для этого требуется [xxxx] быть типом данных географии. Для того, чтобы [xxxx] был типом географии, в строку должна быть применена функция STGeomFromText. И поскольку это единственная часть вашего предложения WHERE, функция должна быть применена к всем строкам.

Если таблица fdx особенно велика, это означает, что функция CLR должна применяться снова и снова. Это не (в терминах SQL-Server) быстрый процесс.

Попробуйте это, если вы можете:

ALTER dbo.fdx ADD Point AS (GEOGRAPHY::Point(Latitude, Longitude, 4326)) PERSISTED 
GO 
CREATE SPATIAL INDEX SIndex_FDX ON dbo.fdx (Point) 
USING GEOGRAPHY_GRID 
WITH (
    GRIDS = (LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH), 
    CELLS_PER_OBJECT = 1 
) 
GO 
DECLARE @Latitude DECIMAL(15,10) = 0 
DECLARE @Longitude DECIMAL(15,10) = 0 
DECLARE @Radius FLOAT = 400 
DECLARE @g GEOGRAPHY = GEOGRAPHY::Point(@Latitude, @Longitude, 4326).STBuffer(@Radius) 
SELECT * FROM dbo.fdx WHERE Point.STIntersects(@g) = 1 

A Примечание: Вы должны преобразовать Шир/пар в десятичных знаков, прежде чем использовать их для вычисления столбца географии. Существует неявное преобразование от float к десятичному в строку, когда вы используете float как вход, который будет обрезать ваши координаты до 4 знаков после запятой. Если вы явно конвертируете сначала, это не будет проблемой.

Кроме того, если у вас есть нулевые значения lat/long в dbo.fdx, вам необходимо отфильтровать их в предложении WHERE, поскольку нулевое значение приведет к неправильной работе вашего пространственного индекса.

+0

Как я уже говорил выше в своем ответе Хасан БИНБОГА, пространственный указатель появился в плане выполнения. Тем не менее, я воссоздал столбец с помощью вашего заявления, и теперь план выполнения отличается. – ancdev

+1

@ancdev Пространственный индекс связан с пространственным столбцом. В вашем запросе вы никогда не ссылаетесь на пространственный столбец, скорее вы используете GEOGRAPHY :: STPointFromText(), который вычисляет пространственное значение, а вычисленное значение по очевидным причинам не может ссылаться на ваш пространственный индекс. – hcaelxxam

0

Вы можете создать пространственный индекс: https://msdn.microsoft.com/en-us/library/bb934196.aspx

+0

Если это так, тогда вы должны использовать подсказку запроса. Добавить: с (index ()) после имени таблицы в предложении «from». Вы будете удивлены, сколько раз мне нужно, чтобы сервер SQL SQL Server использовал правильный индекс при выполнении пространственного запроса. – cungiderm