এসকিউএল সার্ভার ২০০৮ ভৌগলিক ডেটা টাইপ কেন ব্যবহার করবেন?


105

আমি গ্রাহক ডাটাবেসটিকে নতুন করে ডিজাইন করছি এবং তথ্যের একটি নতুন টুকরো আমি স্ট্যান্ডার্ড ঠিকানা ক্ষেত্রগুলির (স্ট্রিট, সিটি, ইত্যাদি) সহ সঞ্চয় করতে চাইছি এটি ঠিকানার ভৌগলিক অবস্থান। আমার মনে একমাত্র ব্যবহারের ক্ষেত্রে ব্যবহারকারীদের গুগল মানচিত্রে স্থানাঙ্কগুলি ম্যাপ করার অনুমতি দেওয়া হয় যখন অন্যথায় ঠিকানাটি পাওয়া যায় না, যা প্রায়শই ঘটে যখন অঞ্চলটি নতুনভাবে বিকশিত হয় বা কোনও প্রত্যন্ত / গ্রামীণ স্থানে থাকে।

আমার প্রথম প্রবণতা ছিল অক্ষাংশ এবং দ্রাঘিমাংশ দশমিক মান হিসাবে সংরক্ষণ করা, কিন্তু তার পরে আমি মনে করি যে এসকিউএল সার্ভার ২০০৮ আর 2 এর একটি 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?


হালনাগাদ

@ এরিক ফিলিপস সঙ্গে সান্নিধ্য অনুসন্ধানের ক্ষমতা নিয়ে এসেছিলেন geography, যা খুব দুর্দান্ত।

অন্যদিকে, একটি দ্রুত পরীক্ষা দেখায় যে selectঅক্ষাংশ এবং দ্রাঘিমাংশ প্রাপ্ত করার জন্য একটি সাধারণ ব্যবহার করার সময় উল্লেখযোগ্যভাবে ধীর হয় geography(নীচে বিশদ)। , এবং অন্য এসও প্রশ্নের গৃহীত উত্তরের বিষয়ে একটি মন্তব্য geographyআমাকে ফাঁস করেছে:

@ সাফুআ আপনাকে স্বাগতম একটি সিডেনোট হিসাবে একটি অযোগ্য জিওগ্রাফি ডেটাটাইপ কলামে একটি স্থানিক সূচক ব্যবহার করা খুব যত্নশীল হতে হবে। কিছু গুরুতর পারফরম্যান্স সমস্যা রয়েছে, সুতরাং আপনার স্কিমাটি পুনর্নির্মাণ করতে হবে এমনকি এমনটিই জিওগ্রাফি কলামটি নন-ন্যাবেল করুন। - টমাস 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)
) 

এবং প্রতিটি টেবিলে একই অক্ষাংশ এবং দ্রাঘিমাংশ মানগুলি ব্যবহার করে একটি একক সারি sertedোকানো হয়েছে:

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

4
আমি উভয়ই করার কথা ভাবছি, ল্যাট এবং লনকে তাদের নিজস্ব কলামে সংরক্ষণ করুন এবং একটি ভূগোলের অবজেক্টের জন্য আরও একটি কলাম আছে, সুতরাং আমার যদি কেবল ল্যাট / লনের প্রয়োজন হয় তবে আমি সেগুলি কলামগুলি থেকে নিয়ে যাব এবং যদি আমার সান্নিধ্য অনুসন্ধানের প্রয়োজন হয় আমি 'ভূগোলটি ব্যবহার করব। এটা কি বুদ্ধিমান? এখানে কি কোনও ডাউনসাইড রয়েছে (এটি ছাড়া আরও বেশি জায়গা লাগে ...)?
ইউভাল এ।

@YuvalA। এটি অবশ্যই যুক্তিসঙ্গত মনে হয় এবং এটি একটি ভাল সমঝোতা হতে পারে। আমার মাথার উপরের অংশে কেবলমাত্র উদ্বেগটি হ'ল টেবিলের ভৌগলিক কলামটি টেবিলের বিপরীতে প্রশ্নের কোনও প্রভাব ফেলছে কিনা - তা নিয়ে আমার কোনও অভিজ্ঞতা নেই তাই যাচাই করার জন্য আপনাকে পরীক্ষা করতে হবে।
জেফ ওগটা

1
আপনি কেন নতুন প্রশ্ন জিজ্ঞাসার পরিবর্তে নতুন প্রশ্ন দিয়ে আপনার প্রশ্ন আপডেট করতে থাকলেন?
চাদ

@ চ্যাড আপনি কী বলতে চাইছেন তা নিশ্চিত হন না। আমি একবার প্রশ্নটির বডি আপডেট করেছি এবং আরও প্রশ্ন জিজ্ঞাসা করা উচিত নয়।
জেফ ওগাটা

6
এই প্রশ্নটি সন্ধানকারীদের জন্য এখন এটি লক্ষ্য করার মতো, যে এসকিউএল সার্ভার ২০১২ সালে স্থানিক ইনডেক্সিংয়ের সাথে উল্লেখযোগ্য কর্মক্ষমতা বৃদ্ধি রয়েছে includes লক্ষণীয় বিষয় হ'ল আপনি যতক্ষণ অবস্থানের তথ্য সংরক্ষণ করছেন ততক্ষণ আপনি আপনার ইতিমধ্যে সঞ্চিত ঠিকানাগুলিকে জিওকোড করার জন্য একটি অনুসন্ধান পরিষেবা ব্যবহার করে স্থানিক তথ্য যোগ করতে পারেন।
ভলভক্স

উত্তর:


66

যদি আপনি কোনও স্থানিক গণনা করার পরিকল্পনা করে থাকেন তবে EF 5.0 লিনকিউ এক্সপ্রেশন যেমন:

private Facility GetNearestFacilityToJobsite(DbGeography jobsite)
{   
    var q1 = from f in context.Facilities            
             let distance = f.Geocode.Distance(jobsite)
             where distance < 500 * 1609.344     
             orderby distance 
             select f;   
    return q1.FirstOrDefault();
}

তারপরে জিওগ্রাফি ব্যবহারের খুব ভাল কারণ রয়েছে।

সত্তা ফ্রেমওয়ার্কের মধ্যে স্থানিক ব্যাখ্যা

উচ্চ কার্যকারিতা স্থানিক ডেটাবেস তৈরির সাথে আপডেট হয়েছে Updated

যেমনটি আমি নোলে আব্রাহামসে উল্লেখ করেছি উত্তর :

স্পেসে একটি নোট, প্রতিটি স্থানাঙ্কটি ডাবল-স্পষ্টতা ফ্লোটিং-পয়েন্ট নম্বর হিসাবে সঞ্চিত হয় যা b৪ বিট (৮ বাইট) দীর্ঘ এবং 8-বাইট বাইনারি মান দশমিক নির্ভুলতার 15 টি সংখ্যার সমান, সুতরাং দশমিকের তুলনা (9) , 6) যা মাত্র 5 বাইট, একেবারে ন্যায্য তুলনা নয়। সত্যিকারের তুলনার জন্য দশমিকের প্রতিটি ল্যাটলংয়ের জন্য সর্বনিম্ন দশমিক (15,12) (9 বাইট) হতে হবে।

সুতরাং স্টোরেজের ধরণের তুলনা করুন:

CREATE TABLE dbo.Geo
(    
geo geography
)
GO

CREATE TABLE dbo.LatLng
(    
    lat decimal(15, 12),   
    lng decimal(15, 12)
)
GO

INSERT dbo.Geo
SELECT geography::Point(12.3456789012345, 12.3456789012345, 4326) 
UNION ALL
SELECT geography::Point(87.6543210987654, 87.6543210987654, 4326) 

GO 10000

INSERT dbo.LatLng
SELECT  12.3456789012345, 12.3456789012345 
UNION
SELECT 87.6543210987654, 87.6543210987654

GO 10000

EXEC sp_spaceused 'dbo.Geo'

EXEC sp_spaceused 'dbo.LatLng'

ফলাফল:

name    rows    data     
Geo     20000   728 KB   
LatLon  20000   560 KB

ভূগোলের ডেটা-টাইপ 30% বেশি স্থান নেয়।

অতিরিক্তভাবে ভূগোলের ডেটাটাইপ কেবলমাত্র একটি পয়েন্ট সংরক্ষণের মধ্যে সীমাবদ্ধ নয়, আপনি লাইনস্ট্রিং, সার্কুলারস্ট্রিং, যৌগিক কর্কভে, বহুভুজ, কার্ভপলিগন, জ্যামিত্রি সংগ্রহ, মাল্টপয়েন্ট, মাল্টিলাইনস্ট্রিং এবং মাল্টিপলিগন এবং আরও অনেক কিছু সঞ্চয় করতে পারেন । এমনকি কোনও ভূগোলের ধরণের (ল্যাট / লং হিসাবে) কোনও বিন্দু ছাড়াই (উদাহরণস্বরূপ লাইনস্ট্রিং (1 1, 2 2) উদাহরণ সংরক্ষণ করার জন্য যে কোনও প্রচেষ্টা প্রতিটি পয়েন্টের জন্য অতিরিক্ত সারি, প্রতিটি পয়েন্টের ক্রমের জন্য সিকোয়েন্সিংয়ের জন্য একটি কলাম ব্যয় করবে লাইনের গ্রুপিংয়ের জন্য আর একটি কলাম। এসকিউএল সার্ভারে ভূগোলের ডেটা ধরণের জন্যও পদ্ধতি রয়েছে যার মধ্যে অঞ্চল, সীমানা, দৈর্ঘ্য, দূরত্ব এবং আরও অনেকগুলি গণনা অন্তর্ভুক্ত ।

SQL সার্ভারে অক্ষাংশ এবং দ্রাঘিমাংশকে দশমিক হিসাবে সংরক্ষণ করা বুদ্ধিমান বলে মনে হচ্ছে।

আপডেট 2

আপনি যদি দূরত্ব, ক্ষেত্র ইত্যাদি ইত্যাদির মতো কোনও গণনা করার পরিকল্পনা করে থাকেন তবে পৃথিবীর পৃষ্ঠের উপরে যথাযথভাবে গণনা করা শক্ত। এসকিউএল সার্ভারে সঞ্চিত প্রতিটি ভূগোলের ধরণের স্থানিক রেফারেন্স আইডি দিয়েও সংরক্ষণ করা হয় । এই আইডিগুলির বিভিন্ন ক্ষেত্র হতে পারে (পৃথিবী 4326)। এর অর্থ হ'ল এসকিউএল সার্ভারে গণনাগুলি প্রকৃতপক্ষে পৃথিবীর পৃষ্ঠের উপরে সঠিকভাবে গণনা করবে (পৃথিবীর পৃষ্ঠের মধ্য দিয়ে যেতে পারে এমন কাক-মাছিগুলির পরিবর্তে )।

এখানে চিত্র বর্ণনা লিখুন


1
এই তথ্যে যোগ করার জন্য, ভূগোলটি ব্যবহার করে সঠিকভাবে বর্গক্ষেত্রের অনুসন্ধানের সক্ষমতা প্রসারিত করা অন্যান্য ল্যাট / লং (সাধারণত কেবল আয়তক্ষেত্র) এর মধ্যে একটি ল্যাট / লম্বা কারণ ভূগোলের ডেটা টাইপ আপনাকে প্রায় কোনও আকার এবং আকারের একাধিক অঞ্চল তৈরি করতে দেয়।
এরিক ফিলিপস

1
আবার ধন্যবাদ. আমি ব্যবহার বিবেচনা করার কারণ জিজ্ঞাসা করেছি geographyএবং আপনি কিছু ভাল সরবরাহ করেছেন। শেষ পর্যন্ত, আমি decimalএই ক্ষেত্রে কেবল ক্ষেত্রগুলি ব্যবহার করার সিদ্ধান্ত নিয়েছি (আমার দীর্ঘ-ঘূর্ণিত আপডেট দেখুন), তবে এটি জেনে রাখা ভাল যে আমি geographyযদি কখনও স্থায়ী ম্যাপিংয়ের চেয়ে কোনও ফ্যানসিয়ার করার প্রয়োজন হয় তবে আমি ব্যবহার করতে পারি।
জেফ ওগাটা

6

আরেকটি বিষয় বিবেচনা করতে হবে হ'ল প্রতিটি পদ্ধতি দ্বারা নেওয়া স্টোরেজ স্পেস। ভূগোলের ধরণটি একটি হিসাবে সংরক্ষণ করা হয় VARBINARY(MAX)। এই স্ক্রিপ্টটি চালানোর চেষ্টা করুন:

CREATE TABLE dbo.Geo
(
    geo geography

)

GO

CREATE TABLE dbo.LatLon
(
    lat decimal(9, 6)
,   lon decimal(9, 6)

)

GO

INSERT dbo.Geo
SELECT geography::Point(36.204824, 138.252924, 4326) UNION ALL
SELECT geography::Point(51.5220066, -0.0717512, 4326) 

GO 10000

INSERT dbo.LatLon
SELECT  36.204824, 138.252924 UNION
SELECT 51.5220066, -0.0717512

GO 10000

EXEC sp_spaceused 'dbo.Geo'
EXEC sp_spaceused 'dbo.LatLon'

ফলাফল:

name    rows    data     
Geo     20000   728 KB   
LatLon  20000   400 KB

ভূগোলের ডেটা-টাইপ প্রায় দ্বিগুণ জায়গা নেয়।


2
স্পেসে একটি নোট, প্রতিটি স্থানাঙ্কটি ডাবল-স্পষ্টতা ফ্লোটিং-পয়েন্ট নম্বর হিসাবে সঞ্চিত হয় যা b৪ বিট (৮ বাইট) দীর্ঘ এবং 8-বাইট বাইনারি মান দশমিক নির্ভুলতার 15 টি সংখ্যার সমান , সুতরাং দশমিকের তুলনা (9) , 6) যা কেবল 5 বাইট , একেবারে ন্যায্য তুলনা নয়। সত্যিকারের তুলনার জন্য দশমিকের প্রতিটি ল্যাটলংয়ের জন্য সর্বনিম্ন দশমিক (15,12) (9 বাইট) হতে হবে।
এরিক ফিলিপস

9
@ এরিক ফিলিপস বিন্দুটি হ'ল কেন আপনার প্রয়োজন সমস্ত দশমিক (9, 6) হলে দশমিক (15, 12) ব্যবহার করবেন? উপরের তুলনাটি একটি ব্যবহারিক - একাডেমিক অনুশীলন নয়।
নোয়েল আবরহামস

-1
    CREATE FUNCTION [dbo].[fn_GreatCircleDistance]
(@Latitude1 As Decimal(38, 19), @Longitude1 As Decimal(38, 19), 
            @Latitude2 As Decimal(38, 19), @Longitude2 As Decimal(38, 19), 
            @ValuesAsDecimalDegrees As bit = 1, 
            @ResultAsMiles As bit = 0)
RETURNS decimal(38,19)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @ResultVar  decimal(38,19)

    -- Add the T-SQL statements to compute the return value here
/*
Credit for conversion algorithm to Chip Pearson
Web Page: www.cpearson.com/excel/latlong.aspx
Email: chip@cpearson.com
Phone: (816) 214-6957 USA Central Time (-6:00 UTC)
Between 9:00 AM and 7:00 PM

Ported to Transact SQL by Paul Burrows BCIS
*/
DECLARE  @C_RADIUS_EARTH_KM As Decimal(38, 19)
SET @C_RADIUS_EARTH_KM = 6370.97327862
DECLARE  @C_RADIUS_EARTH_MI As Decimal(38, 19)
SET @C_RADIUS_EARTH_MI = 3958.73926185
DECLARE  @C_PI As Decimal(38, 19)
SET @C_PI =  pi()

DECLARE @Lat1 As Decimal(38, 19)
DECLARE @Lat2 As Decimal(38, 19)
DECLARE @Long1 As Decimal(38, 19)
DECLARE @Long2 As Decimal(38, 19)
DECLARE @X As bigint
DECLARE @Delta As Decimal(38, 19)

If @ValuesAsDecimalDegrees = 1 
Begin
    set @X = 1
END
Else
Begin
    set @X = 24
End 

-- convert to decimal degrees
set @Lat1 = @Latitude1 * @X
set @Long1 = @Longitude1 * @X
set @Lat2 = @Latitude2 * @X
set @Long2 = @Longitude2 * @X

-- convert to radians: radians = (degrees/180) * PI
set @Lat1 = (@Lat1 / 180) * @C_PI
set @Lat2 = (@Lat2 / 180) * @C_PI
set @Long1 = (@Long1 / 180) * @C_PI
set @Long2 = (@Long2 / 180) * @C_PI

-- get the central spherical angle
set @Delta = ((2 * ASin(Sqrt((power(Sin((@Lat1 - @Lat2) / 2) ,2)) + 
    Cos(@Lat1) * Cos(@Lat2) * (power(Sin((@Long1 - @Long2) / 2) ,2))))))

If @ResultAsMiles = 1 
Begin
    set @ResultVar = @Delta * @C_RADIUS_EARTH_MI
End
Else
Begin
    set @ResultVar = @Delta * @C_RADIUS_EARTH_KM
End

    -- Return the result of the function
    RETURN @ResultVar

END

2
নতুন উত্তর সর্বদা স্বাগতম, তবে দয়া করে কিছু প্রসঙ্গ যুক্ত করুন। উপরোক্ত বিষয়টি কীভাবে সমাধান করে তা সংক্ষেপে ব্যাখ্যা করে উত্তরটি অন্যদের কাছে আরও কার্যকর করে তোলে।
লেইগ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.