我正在重新设计一个客户数据库,我想与标准地址字段(街道,城市等)一起存储的新信息之一就是地址的地理位置。我要记住的唯一用例是,当找不到地址时,允许用户在Google地图上绘制坐标,这通常是在新开发的区域或位于偏远/农村位置时发生。
我的第一个倾向是将纬度和经度存储为十进制值,但是后来我想起了SQL Server 2008 R2具有geography
数据类型。我绝对没有使用过的经验geography
,并且从我的初步研究来看,对于我的情况而言,这似乎有些过分。
例如,要使用存储为的纬度和经度decimal(7,4)
,我可以这样做:
insert into Geotest(Latitude, Longitude) values (47.6475, -122.1393)
select Latitude, Longitude from Geotest
但是使用geography
,我可以这样做:
insert into Geotest(Geolocation) values (geography::Point(47.6475, -122.1393, 4326))
select Geolocation.Lat, Geolocation.Long from Geotest
尽管没有那么复杂,但是如果不需要的话,为什么还要增加复杂性呢?
在放弃使用的想法之前geography
,我应该考虑什么?使用空间索引搜索位置是否比索引纬度和经度字段更快?使用geography
我没有意识到的优点吗?或者,另一方面,我应该知道哪些警告会阻止我使用geography
?
更新资料
@Erik Philips带来了使用进行邻近搜索的功能geography
,这非常酷。
另一方面,一项快速测试显示,使用时,简单select
地获取经度和纬度会明显变慢geography
(详细信息如下)。,而对另一个SO问题的公认答案的评论geography
让我很不高兴:
@SaphuA不客气。作为一个附带说明,非常小心使用可为null的GEOGRAPHY数据类型列上的空间索引。存在一些严重的性能问题,因此即使您必须重新构建架构,也应使GEOGRAPHY列不可为空。–托马斯6月18日11:18
总而言之,在权衡进行邻近搜索的可能性与性能和复杂性之间的权衡之后,我决定放弃geography
在这种情况下的使用。
我运行的测试的详细信息:
我创建了两个表,一个使用geography
,另一条使用decimal(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
不存在的where ,geography
速度仍然很慢:
GeographyDuration LatLongDuration
----------------- ---------------
1607 948
1610 946
1607 947
AvgGeographyDuration AvgLatLongDuration
-------------------- ------------------
1608 947