What is the ideal data type to use when storing latitude / longitude in a MySQL database?

前端 未结 21 2370
梦如初夏
梦如初夏 2020-11-22 09:40

Bearing in mind that I\'ll be performing calculations on lat / long pairs, what datatype is best suited for use with a MySQL database?

相关标签:
21条回答
  • 2020-11-22 10:22

    Depends on the precision that you require.

    Datatype           Bytes       resolution
    ------------------ -----  --------------------------------
    Deg*100 (SMALLINT)     4  1570 m    1.0 mi  Cities
    DECIMAL(4,2)/(5,2)     5  1570 m    1.0 mi  Cities
    SMALLINT scaled        4   682 m    0.4 mi  Cities
    Deg*10000 (MEDIUMINT)  6    16 m     52 ft  Houses/Businesses
    DECIMAL(6,4)/(7,4)     7    16 m     52 ft  Houses/Businesses
    MEDIUMINT scaled       6   2.7 m    8.8 ft
    FLOAT                  8   1.7 m    5.6 ft
    DECIMAL(8,6)/(9,6)     9    16cm    1/2 ft  Friends in a mall
    Deg*10000000 (INT)     8    16mm    5/8 in  Marbles
    DOUBLE                16   3.5nm     ...    Fleas on a dog
    

    From: http://mysql.rjweb.org/doc.php/latlng

    To summarise:

    • The most precise available option is DOUBLE.
    • The most common seen type used is DECIMAL(8,6)/(9,6).

    As of MySQL 5.7, consider using Spatial Data Types (SDT), specifically POINT for storing a single coordinate. Prior to 5.7, SDT does not support indexes (with exception of 5.6 when table type is MyISAM).

    Note:

    • When using POINT class, the order of the arguments for storing coordinates must be POINT(latitude, longitude).
    • There is a special syntax for creating a spatial index.
    • The biggest benefit of using SDT is that you have access to Spatial Analyses Functions, e.g. calculating distance between two points (ST_Distance) and determining whether one point is contained within another area (ST_Contains).
    0 讨论(0)
  • 2020-11-22 10:23

    We store latitude/longitude X 1,000,000 in our oracle database as NUMBERS to avoid round off errors with doubles.

    Given that latitude/longitude to the 6th decimal place was 10 cm accuracy that was all we needed. Many other databases also store lat/long to the 6th decimal place.

    0 讨论(0)
  • 2020-11-22 10:23

    TL;DR

    Use FLOAT(8,5) if you're not working in NASA / military and not making aircrafts navi systems.


    To answer your question fully, you'd need to consider several things:

    Format

    • degrees minutes seconds: 40° 26′ 46″ N 79° 58′ 56″ W
    • degrees decimal minutes: 40° 26.767′ N 79° 58.933′ W
    • decimal degrees 1: 40.446° N 79.982° W
    • decimal degrees 2: -32.60875, 21.27812
    • Some other home-made format? Noone forbids you from making your own home-centric coordinates system and store it as heading and distance from your home. This could make sense for some specific problems you're working on.

    So the first part of the answer would be - you can store the coordinates in the format your application uses to avoid constant conversions back and forth and make simpler SQL queries.

    Most probably you use Google Maps or OSM to display your data, and GMaps are using "decimal degrees 2" format. So it will be easier to store coordinates in the same format.

    Precision

    Then, you'd like to define precision you need. Of course you can store coordinates like "-32.608697550570334,21.278081997935146", but have you ever cared about millimeters while navigation to the point? If you're not working in NASA and not doing satellites or rockets or planes trajectories, you should be fine with several meters accuracy.

    Commonly used format is 5 digits after dots which gives you 50cm accuracy.

    Example: there is 1cm distance between X,21.2780818 and X,21.2780819. So 7 digits after dot give you 1/2cm precision and 5 digits after dot will give you 1/2 meters precision (because minimal distance between distinct points is 1m, so rounding error cannot be more than half of it). For most civil purposes it should be enough.

    degrees decimal minutes format (40° 26.767′ N 79° 58.933′ W) gives you exactly the same precision as 5 digits after dot

    Space-efficient storage

    If you've selected decimal format, then your coordinate is a pair (-32.60875, 21.27812). Obviously, 2 x (1 bit for sign, 2 digits for degrees and 5 digits for exponent) will be enough.

    So here I'd like to support Alix Axel from comments saying that Google suggestion to store it in FLOAT(10,6) is really extra, because you don't need 4 digits for main part (since sign is separated and latitude is limited to 90 and longitude is limited to 180). You can easily use FLOAT(8,5) for 1/2m precision or FLOAT(9,6) for 50/2cm precision. Or you can even store lat and long in separated types, because FLOAT(7,5) is enough for lat. See MySQL float types reference. Any of them will be like normal FLOAT and equal to 4 bytes anyway.

    Usually space is not an issue nowadays, but if you want to really optimize the storage for some reason (Disclaimer: don't do pre-optimization), you may compress lat(no more than 91 000 values + sign) + long(no more than 181 000 values + sign) to 21 bits which is significantly less than 2xFLOAT (8 bytes == 64 bits)

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