Je suis la refonte d'un client de base de données et l'un des nouveaux éléments d'information, je voudrais stocker avec la norme champs d'adresse (Rue, Ville, etc.) est l'emplacement géographique de l'adresse. Le seul cas d'utilisation j'ai à l'esprit est de permettre aux utilisateurs de la carte les coordonnées sur Google maps lorsque l'adresse ne peut pas être trouvé, ce qui arrive souvent lorsque la zone est nouvellement développé, ou est dans une distance/zone rurale.
Mon premier réflexe a été de stocker la latitude et la longitude des valeurs décimales, mais ensuite je me suis souvenu que SQL Server 2008 R2 a un geography
type de données. Je n'ai absolument aucune expérience geography
, et de ma recherche initiale, il semble être trop pour mon scénario.
Par exemple, pour travailler avec la latitude et la longitude stockées en tant que decimal(7,4)
, je peux faire ceci:
insert into Geotest(Latitude, Longitude) values (47.6475, -122.1393)
select Latitude, Longitude from Geotest
mais avec geography
, je ferais ceci:
insert into Geotest(Geolocation) values (geography::Point(47.6475, -122.1393, 4326))
select Geolocation.Lat, Geolocation.Long from Geotest
Bien que ce n'est pas que beaucoup plus compliqué, pourquoi ajouter de la complexité si je n'ai pas?
Avant de m'abandonner l'idée d'utiliser geography
, est-il quelque chose que je dois prendre en compte? Serait-il plus rapide pour rechercher un emplacement, à l'aide d'un index spatial contre l'indexation de la Latitude et la Longitude des champs? Existe-il des avantages à utiliser le geography
que je ne suis pas au courant? Ou, sur le revers de la médaille, il y a les mises en garde que je devrais savoir au sujet de ce qui allait me décourager d'utiliser geography
?
Mise à jour
@Erik Philips a évoqué la possibilité de faire des recherches de proximité avec geography
, ce qui est très cool.
D'autre part, un test rapide montre qu'un simple select
pour obtenir la latitude et la longitude est significativement plus lente lors de l'utilisation d' geography
(détails ci-dessous). et un commentaire sur la accepté de répondre à l'autre question sur geography
a me méfier:
@SaphuA Vous êtes les bienvenus. Au passage être TRÈS prudent de à l'aide d'un index spatial sur une nullable GÉOGRAPHIE colonne de type de données. Il y a quelques grave problème de performance, afin de faire de la GÉOGRAPHIE de la colonne non nullable même si vous devez rénover votre schéma. – Tomas 18 Juin à 11:18
Dans l'ensemble, peser la probabilité de faire des recherches de proximité contre le commerce de la performance et de la complexité, j'ai décidé de renoncer à l'utilisation de l' geography
dans ce cas.
Détails de l'épreuve j'ai couru:
J'ai créé deux tables, l'une utilisant geography
et un autre à l'aide de decimal(9,6)
de la latitude et de la longitude:
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)
)
et d'insérer une seule ligne, en utilisant les mêmes valeurs de latitude et longitude dans chaque table:
insert into GeographyTest(Location) values (geography::Point(47.6475, -122.1393, 4326))
insert into LatLongTest(Latitude, Longitude) values (47.6475, -122.1393)
Enfin, l'exécution du code suivant montre que, sur ma machine, la sélection de la latitude et de longitude est environ 5 fois plus lente lors de l'utilisation d' 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
Résultats:
GeographyDuration LatLongDuration
----------------- ---------------
5146 1020
5143 1016
5169 1030
AvgGeographyDuration AvgLatLongDuration
-------------------- ------------------
5152 1022
Ce qui était plus surprenant, c'est que même lorsque aucune ligne n'est sélectionnée, par exemple en sélectionnant où RowId = 2
, ce qui n'existe pas, geography
a été encore plus lente:
GeographyDuration LatLongDuration
----------------- ---------------
1607 948
1610 946
1607 947
AvgGeographyDuration AvgLatLongDuration
-------------------- ------------------
1608 947