ฉันกำลังออกแบบฐานข้อมูลลูกค้าใหม่และหนึ่งในข้อมูลใหม่ที่ฉันต้องการจัดเก็บพร้อมกับช่องที่อยู่มาตรฐาน (ถนนเมือง ฯลฯ ) คือที่ตั้งทางภูมิศาสตร์ของที่อยู่ กรณีการใช้งานเดียวที่ฉันนึกถึงคืออนุญาตให้ผู้ใช้ทำแผนที่พิกัดบนแผนที่ 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 ยินดีต้อนรับครับ ในฐานะที่เป็นด้านข้างควรระมัดระวังอย่างยิ่งในการใช้ดัชนีเชิงพื้นที่บนคอลัมน์ประเภทข้อมูล GEOGRAPHY ที่เป็นโมฆะ มีปัญหาด้านประสิทธิภาพที่ร้ายแรงดังนั้นทำให้คอลัมน์ GEOGRAPHY นั้นไม่เป็นโมฆะแม้ว่าคุณจะต้องสร้างสคีมาใหม่ก็ตาม - Tomas 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
ที่ไม่มีอยู่ แต่geography
ก็ยังช้ากว่า:
GeographyDuration LatLongDuration
----------------- ---------------
1607 948
1610 946
1607 947
AvgGeographyDuration AvgLatLongDuration
-------------------- ------------------
1608 947