Why use the SQL Server 2008 geography data type?

前端 未结 3 902
旧巷少年郎
旧巷少年郎 2021-01-29 18:04

I am redesigning a customer database and one of the new pieces of information I would like to store along with the standard address fields (Street, City, etc.) is the geographic

相关标签:
3条回答
  • 2021-01-29 18:38
        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
    
    0 讨论(0)
  • 2021-01-29 18:43

    Another thing to consider is the storage space taken up by each method. The geography type is stored as a VARBINARY(MAX). Try running this script:

    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'
    

    Result:

    name    rows    data     
    Geo     20000   728 KB   
    LatLon  20000   400 KB
    

    The geography data-type takes up almost twice as much space.

    0 讨论(0)
  • 2021-01-29 18:48

    If you plan on doing any spatial computation, EF 5.0 allows LINQ Expressions like:

    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();
    }
    

    Then there is a very good reason to use Geography.

    Explanation of spatial within Entity Framework.

    Updated with Creating High Performance Spatial Databases

    As I noted on Noel Abrahams Answer:

    A note on space, each coordinate is stored as a double-precision floating-point number that is 64 bits (8 bytes) long, and 8-byte binary value is roughly equivalent to 15 digits of decimal precision, so comparing a decimal(9,6) which is only 5 bytes, isn't exactly a fair comparison. Decimal would have to be a minimum of Decimal(15,12) (9 bytes) for each LatLong (total of 18 bytes) for a real comparison.

    So comparing storage types:

    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'
    

    Result:

    name    rows    data     
    Geo     20000   728 KB   
    LatLon  20000   560 KB
    

    The geography data-type takes up 30% more space.

    Additionally the geography datatype is not limited to only storing a Point, you can also store LineString, CircularString, CompoundCurve, Polygon, CurvePolygon, GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon and more. Any attempt to store even the simplest of Geography types (as Lat/Long) beyond a Point (for example LINESTRING(1 1, 2 2) instance) will incur additional rows for each point, a column for sequencing for the order of each point and another column for grouping of lines. SQL Server also has methods for the Geography data types which include calculating Area, Boundary, Length, Distances, and more.

    It seems unwise to store Latitude and Longitude as Decimal in Sql Server.

    Update 2

    If you plan on doing any calculations like distance, area, etc, properly calculating these over the surface of the earth is difficult. Each Geography type stored in SQL Server is also stored with a Spatial Reference ID. These id's can be of different spheres (the earth is 4326). This means that the calculations in SQL Server will actually calculate correctly over the surface of the earth (instead of as-the-crow-flies which could be through the surface of the earth).

    enter image description here

    0 讨论(0)
提交回复
热议问题