Зачем использовать тип данных geography SQL Server 2008?

Я модифицирую базу данных клиентов, и одна из новых частей информации, которую я хотел бы сохранить вместе со стандартными полями адреса (улица, город и т. д.), - это географическое расположение адрес. Единственный вариант использования, который я имею в виду, - это позволить пользователям отображать координаты на картах Google, когда адрес не может быть найден иным образом, что часто случается, когда район только что застраивается или находится в удаленном / сельском районе.

Сначала я хотел сохранить широту и долготу в виде десятичных значений, но потом я вспомнил, что SQL Server 2008 R2 имеет тип данных geography . У меня нет абсолютно никакого опыта использования географии , и, судя по моим первоначальным исследованиям, это кажется излишним для моего сценария.

Например, чтобы работать с широтой и долготой, сохраненными в виде десятичного числа (7,4) , я могу сделать следующее:

insert into Geotest(Latitude, Longitude) values (47.6475, -122.1393)
select Latitude, Longitude from Geotest

но с географией я бы сделал следующее:

insert into Geotest(Geolocation) values (geography::Point(47.6475, -122.1393, 4326))
select Geolocation.Lat, Geolocation.Long from Geotest

Хотя это не , что намного сложнее, зачем добавлять сложность, если мне это не нужно?

Прежде чем я откажусь от идеи использования географии , могу ли я что-нибудь добавить? следует учитывать? Было бы быстрее искать местоположение, используя пространственный индекс, по сравнению синдексировать поля широты и долготы? Есть ли преимущества использования географии , о которых я не знаю? Или, с другой стороны, есть ли предостережения, о которых я должен знать, которые отговорили бы меня от использования географии ?


Обновление

@Erik Philips предоставил возможность выполнять поиск по близости с помощью ] география , что очень круто.

С другой стороны, быстрый тест показывает, что простой select для получения широты и долготы значительно медленнее при использовании geography (подробности ниже). , и комментарий к принятому ответу на другой вопрос SO по географии вызывает у меня подозрение:

@SaphuA Пожалуйста. В качестве примечания будьте ОЧЕНЬ осторожны при использовании пространственного индекса для столбца типа данных GEOGRAPHY, допускающего значение NULL. Существует несколько серьезных проблем с производительностью, поэтому сделайте этот столбец GEOGRAPHY не допускающим значения NULL , даже если вам нужно изменить схему. - Томас 18 июня, 11:18

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


Подробная информация о проведенном мной тесте:

Я создал две таблицы, одну с использованием geography , а другую с использованием десятичного числа (9,6) для широты и долготы:

CREATE TABLE [dbo].[GeographyTest]
(
    [RowId] [int] IDENTITY(1,1) NOT NULL,
    [Location] [geography] NOT NULL,
    CONSTRAINT [PK_GeographyTest] PRIMARY KEY CLUSTERED ( [RowId] ASC )
) 

CREATE TABLE [dbo].[LatLongTest]
(
    [RowId] [int] IDENTITY(1,1) NOT NULL,
    [Latitude] [decimal](9, 6) NULL,
    [Longitude] [decimal](9, 6) NULL,
    CONSTRAINT [PK_LatLongTest] PRIMARY KEY CLUSTERED ([RowId] ASC)
) 

и вставил одну строку с одинаковыми значениями широты и долготы в каждую таблицу:

insert into GeographyTest(Location) values (geography::Point(47.6475, -122.1393, 4326))
insert into LatLongTest(Latitude, Longitude) values (47.6475, -122.1393)

Наконец, выполнение следующего кода показывает, что на моем компьютере выбор широты и долготы примерно в 5 раз медленнее при использовании geography ].

declare @lat float, @long float,
        @d datetime2, @repCount int, @trialCount int, 
        @geographyDuration int, @latlongDuration int,
        @trials int = 3, @reps int = 100000

create table #results 
(
    GeographyDuration int,
    LatLongDuration int
)

set @trialCount = 0

while @trialCount < @trials
begin

    set @repCount = 0
    set @d = sysdatetime()

    while @repCount < @reps
    begin
        select @lat = Location.Lat,  @long = Location.Long from GeographyTest where RowId = 1
        set @repCount = @repCount + 1
    end

    set @geographyDuration = datediff(ms, @d, sysdatetime())

    set @repCount = 0
    set @d = sysdatetime()

    while @repCount < @reps
    begin
        select @lat = Latitude,  @long = Longitude from LatLongTest where RowId = 1
        set @repCount = @repCount + 1
    end

    set @latlongDuration = datediff(ms, @d, sysdatetime())

    insert into #results values(@geographyDuration, @latlongDuration)

    set @trialCount = @trialCount + 1

end

select * 
from #results

select avg(GeographyDuration) as AvgGeographyDuration, avg(LatLongDuration) as AvgLatLongDuration
from #results

drop table #results

Результаты:

GeographyDuration LatLongDuration
----------------- ---------------
5146              1020
5143              1016
5169              1030

AvgGeographyDuration AvgLatLongDuration
-------------------- ------------------
5152                 1022

Что было более удивительно, так это то, что даже когда не выбраны никакие строки, например при выборе, где RowId = 2 , которого не существует, география все еще оставалась медленнее:

GeographyDuration LatLongDuration
----------------- ---------------
1607              948
1610              946
1607              947

AvgGeographyDuration AvgLatLongDuration
-------------------- ------------------
1608                 947

104
задан Community 23 May 2017 в 12:34
поделиться