Apa tipe data ideal untuk digunakan saat menyimpan lintang / bujur dalam database MySQL?


432

Mengingat bahwa saya akan melakukan perhitungan pada pasangan lat / long, tipe data apa yang paling cocok untuk digunakan dengan database MySQL?


1
Saya menemukan tautan ini sangat berguna: howto-use-mysql-spatial-ext.blogspot.com/2007/11/… Mungkin sedikit lebih tua, tetapi berisi penjelasan lengkap termasuk contoh.
madc

Saya kebanyakan orang di sini tidak mengerti apa yang terjadi. Segera setelah kode aplikasi menyentuh angka, asalkan salah satu menggunakan ganda (yang paling banyak dilakukan), angka berubah menjadi paling presisi ganda . Menyimpannya bahkan dengan sejuta desimal tidak akan ada gunanya. Menyimpannya dengan jumlah desimal yang terbatas (mis. 6) menghancurkan bagian dari ketepatan itu dan menambahkan akumulasi kesalahan setiap kali ia ditulis ulang ke dalam basis data . Double membawa sekitar 16 angka penting, berpotensi semua desimal. Memotong 10 dari mereka membuat kesalahan akumulasi dari waktu ke waktu. Itu adalah "titik mengambang" karena alasan. Lanj.
Stormwind

Cont: 6 desimal mungkin ok ketika menyimpan angka yang diperoleh dari sumber eksternal, tidak diubah dan untuk pertama kalinya - sebagai bahan sumber. Tetapi jika melakukan perhitungan bahkan sekali, dan menyimpannya lagi, bodoh untuk menghapus bagian dari ketepatannya dengan menerapkan format desimal tertentu. Melakukan perhitungan hanya di dalam server mungkin berbeda (server mungkin atau mungkin tidak menggunakan sesuatu yang lain dari dua kali lipat secara internal), dan menggunakan representasi numerik yang lebih buruk daripada dua kali lipat dalam perhitungan aplikasi ofc mengurangi kebutuhan untuk presisi penyimpanan.
Stormwind

Cont: JIKA server menyimpan nomor dengan presisi yang lebih tinggi, meskipun diklaim "9,6" (yang saya tidak tahu jika itu), maka tidak ada yang penting, dan formatnya murni masalah kenyamanan - tidak banyak yang bisa dilakukan. lakukan dengan masalah presisi. Tetapi saya tidak akan terkejut jika server benar-benar membulatkan angka menjadi presisi 6 desimal dengan format itu.
Stormwind

Cont: Akhirnya: Untuk lat, lon, desimal ke-6 adalah soal menjepit ke dalam ca. Kisi 11-sentimeter. Setiap kali seseorang membaca (menyentuh), menghitung dan menyimpan lagi, dengan 6 desimal, akan ada gertakan baru (= akumulasi kesalahan). Jika semua kesalahan terjadi pada arah yang sama, akan ada kesalahan besar . Jika melakukan perkalian sementara di atasnya (mis. Naik, turunkan dan turunkan), itu mungkin tumbuh lebih besar. Jangan memotong presisi tanpa alasan yang bagus!
Stormwind

Jawaban:


161

Gunakan ekstensi spasial MySQL dengan GIS.


25
Apakah Anda memiliki tautan lain ke contoh atau info lain tentang cara terbaik untuk memulai dengan mereka?
Codebeef

6
MYSQL Spatial adalah pilihan yang baik, tetapi masih memiliki batasan dan peringatan yang signifikan (per 6). Silakan lihat jawaban saya di bawah ini ...
James Schek

1
@ James Schek benar. Plus, MySQL melakukan semua kalkulasinya menggunakan geometri euclidean, jadi itu tidak mewakili kasus penggunaan dunia nyata untuk lat / lng.
mkuech

FYI; Mysql hanya mendukung indeks spasial dengan tabel * .myisam, yaitu mesin ISAM. Tautan: dev.mysql.com/doc/refman/5.0/en/creating-spatial-indexes.html
PodTech.io

Lihatlah artikel ini di bagian Pembaruan terakhir: mysqlserverteam.com/mysql-5-7-and-gis-an-example
Jaspal Singh

150

Google menyediakan solusi PHP / MySQL awal hingga akhir untuk contoh aplikasi "Pencari Lokasi" dengan Google Maps. Dalam contoh ini, mereka menyimpan nilai lat / lng sebagai "Float" dengan panjang "10,6"

http://code.google.com/apis/maps/articles/phpsqlsearch.html


11
Google jelas tidak mengerti bagaimana spesifikasi FLOAT bekerja: FLOAT(10,6)menyisakan 4 digit untuk bagian integer dari koordinat. Dan tidak, tandanya tidak masuk hitungan - yang berasal dari atribut yang ditandatangani.
Alix Axel

2
Tetapi jika Anda perlu menyimpan sebagai nilai bagian integral dari [0, 180] harus lebih dari cukup, bukan?
Hrvoje Golcic

37
@AlixAxel Saya pikir Google tahu apa yang dilakukannya. Karena menyatakan bahwa: " Dengan kemampuan zoom Google Maps saat ini, Anda seharusnya hanya membutuhkan 6 digit ketelitian setelah desimal. Itu akan membuat bidang menyimpan 6 digit setelah desimal, ditambah hingga 4 digit sebelum desimal, misalnya - 123.456789 derajat. " Jika unsigned dicentang, polanya akan menjadi 1234.567890 . Jadi tidak ada masalah.
1.44mb

16
@AlixAxel Dia menghitung angka-angka dalam urutan; tidak menggunakan koordinat aktual ...
Andrew Ellis

8
Menggunakan datatype Doubleuntuk Laravel
FooBar

134

Pada dasarnya itu tergantung pada presisi yang Anda butuhkan untuk lokasi Anda. Menggunakan DOUBLE Anda akan memiliki ketelitian 3,5nm. DECIMAL (8,6) / (9,6) turun hingga 16cm. FLOAT adalah 1,7m ...

Tabel yang sangat menarik ini memiliki daftar yang lebih lengkap: http://mysql.rjweb.org/doc.php/latlng :

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

Semoga ini membantu.


2
Saya perlu menulis komentar yang konstruktif dan terperinci yang berfokus pada isi tulisan, jadi saya akan mengatakan bahwa sambil mengamati tabel akurasi yang disediakan oleh situs web Rick James, saya agak geli pada deskripsi resolusi "kutu pada anjing" dan merasa layak untuk pujian. Secara teknis, ini adalah penggambaran yang membantu saya dalam menentukan tipe data apa yang akan digunakan ketika menyimpan koordinat untuk mengukur jarak antara dua alamat, yang, @Simon, saya ingin mengucapkan terima kasih karena telah berbagi.
Sam_Butler

FWIW, penggunaan tautan "skala kecil" tautan itu sangat tidak efisien. Jawaban Oguzhan adalah cara terbaik untuk menyimpan long / lat dengan 7 digit setelah titik desimal, dalam int yang bertanda 4 byte. Sangat presisi (~ 1cm) dalam ukuran kecil (4B).
ToolmakerSteve

74

Ekstensi Spasial MySQL adalah pilihan terbaik karena Anda memiliki daftar lengkap operator spasial dan indeks yang Anda inginkan. Indeks spasial akan memungkinkan Anda untuk melakukan perhitungan berbasis jarak dengan sangat cepat. Harap diingat bahwa pada 6.0, Ekstensi Spasial masih belum lengkap. Saya tidak meletakkan MySQL Spatial, hanya memberi tahu Anda tentang jebakan sebelum Anda terlalu jauh dalam hal ini.

Jika Anda hanya berurusan dengan poin dan hanya fungsi JARAK, ini baik-baik saja. Jika Anda perlu melakukan perhitungan apa pun dengan Polygons, Lines, atau Buffered-Points, operator spasial tidak memberikan hasil yang tepat kecuali Anda menggunakan operator "relate". Lihat peringatan di atas 21.5.6 . Hubungan seperti berisi, di dalam, atau berpotongan menggunakan MBR, bukan bentuk geometri yang tepat (yaitu Ellipse diperlakukan seperti Rectangle).

Juga, jarak dalam MySQL Spatial berada dalam satuan yang sama dengan geometri pertama Anda. Ini berarti jika Anda menggunakan Derajat Desimal, maka pengukuran jarak Anda dalam Derajat Desimal. Ini akan membuatnya sangat sulit untuk mendapatkan hasil yang tepat saat Anda mendapatkan furthur dari garis katulistiwa.


26
Restating: MySQL Spatial Extensions tidak cocok untuk menghitung jarak lingkaran besar antara titik-titik di permukaan bumi yang diwakili oleh lat / long. Fungsi jarak mereka, dll, hanya berguna pada cartesian, planar, koordinat.
O. Jones

71

Ketika saya melakukan ini untuk database navigasi yang dibangun dari ARINC424 saya melakukan cukup banyak pengujian dan melihat kembali kode, saya menggunakan DECIMAL (18,12) (Sebenarnya sebuah NUMERIC (18,12) karena itu firebird).

Mengapung dan ganda tidak seakurat dan dapat menyebabkan kesalahan pembulatan yang mungkin merupakan hal yang sangat buruk. Saya tidak ingat apakah saya menemukan data nyata yang memiliki masalah - tetapi saya cukup yakin bahwa ketidakmampuan untuk menyimpan secara akurat dalam float atau double dapat menyebabkan masalah.

Intinya adalah bahwa ketika menggunakan derajat atau radian kita tahu rentang nilai - dan bagian fraksional membutuhkan angka paling banyak.

The MySQL Spatial Ekstensi adalah alternatif yang baik karena mereka mengikuti The OpenGIS Geometri Model . Saya tidak menggunakannya karena saya perlu menjaga portable database saya.


3
Terima kasih, ini sangat membantu. Rasanya aneh membaca semua pertanyaan dan jawaban dari 2008 menyadari itu sudah 8 tahun yang lalu.
aexl

1
@TheSexiestManinJamaica - Sebelum IEEE 754-1985, perangkat keras floating-point komputer kacau. Bahkan ada pada mesin a*byang tidak sama b*a(untuk beberapa nilai). Ada banyak contoh agak seperti: 2+2 = 3.9999. Standar membersihkan banyak kekacauan, dan 'cepat' diadopsi oleh hampir setiap perangkat keras dan perangkat lunak. Jadi, diskusi ini telah berlaku, tidak hanya sejak 2008, tetapi untuk sepertiga abad.
Rick James

42

Tergantung pada presisi yang Anda butuhkan.

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

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

Untuk meringkas:

  • Opsi yang tersedia paling tepat adalah DOUBLE.
  • Jenis terlihat paling umum digunakan adalah DECIMAL(8,6)/(9,6).

Pada MySQL 5.7 , pertimbangkan untuk menggunakan Jenis Data Spasial (SDT), khusus POINTuntuk menyimpan satu koordinat. Sebelum 5.7, SDT tidak mendukung indeks (dengan pengecualian 5.6 ketika tipe tabel adalah MyISAM).

catatan:

  • Saat menggunakan POINTkelas, urutan argumen untuk menyimpan koordinat harus POINT(latitude, longitude).
  • Ada sintaks khusus untuk membuat indeks spasial .
  • Manfaat terbesar menggunakan SDT adalah Anda memiliki akses ke Fungsi Analisis Spasial , misalnya menghitung jarak antara dua titik ( ST_Distance) dan menentukan apakah satu titik terkandung dalam area lain ( ST_Contains).

2
Anda menyalin bagian yang disisipkan dari jawaban sebelumnya dan "meringkas" dengan sesuatu yang tidak direkomendasikan oleh orang yang membuat tabel itu : «Bagaimana cara PARTISI? Yah, MySQL sangat pemilih. Jadi FLOAT / GANDA keluar. DECIMAL keluar. Jadi, kami terjebak dengan beberapa kludge. Intinya, kita perlu mengonversi Lat / Lng ke beberapa ukuran INT dan menggunakan PARTITION BY RANGE. » DAN «FLOAT memiliki 24 bit signifikan; DOUBLE memiliki 53. (Mereka tidak bekerja dengan PARTITIONing tetapi termasuk untuk kelengkapan. Seringkali orang menggunakan DOUBLE tanpa menyadari berapa banyak yang diperlukan , dan berapa banyak ruang yang diperlukan.) »Biarkan saja bagian SDT yang Anda tulis.
Armfoot

1
@ Kaki Kaki Jika Anda melihat pada saat pengeditan, itu adalah jawaban lain yang disalin dari saya. Bukan itu yang penting: Saya melihat Stack Overflow lebih dari "catatan untuk masa depan saya".
Gajus

1
Tidak, dia tidak menyalin dari Anda, dia hanya menempel tabel seperti yang Anda lakukan dari tautan yang dirujuk pada 2014 (posting Anda dari 2015). Btw, saya pikir Anda salah mengeja "Khusus" ketika Anda menautkan Jenis Data Spasial . Bagian yang Anda tulis ini sebenarnya berguna untuk orang yang ingin mulai menggunakannya, jika Anda menambahkan beberapa contoh seperti CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;dan peringatan tentang batasan SDT, seperti yang disebutkan James , mungkin jawaban Anda akan lebih ringkas dan tepat dalam membantu orang lain juga. ..
Armfoot

@Gajus - Saya merasa terhormat bahwa Anda berdua menemukan dokumen saya! (Tidak, saya tidak tahu seberapa besar kutu, tetapi saya merasa itu akan menarik perhatian seseorang.)
Rick James

Saat menggunakan kelas TITIK, urutan argumen untuk menyimpan koordinat harus TITIK (bujur / X, lintang / Y).
AndreyP


19

Gunakan DECIMAL(8,6)untuk garis lintang (90 hingga -90 derajat) dan DECIMAL(9,6)untuk garis bujur (180 hingga -180 derajat). 6 tempat desimal baik untuk sebagian besar aplikasi. Keduanya harus "ditandatangani" untuk memungkinkan nilai negatif.


DECIMALjenis ini dimaksudkan untuk perhitungan keuangan di mana tidak ada floor/ceilyang diterima. Polos FLOATsecara signifikan mengungguli DECIMAL.
Kondybas

1
@Kondybas - Karena biaya utama dalam database adalah mengambil baris, perbedaan kinerja antara float dan desimal seharusnya tidak menjadi perhatian.
Rick James

14

Tidak perlu melangkah jauh, menurut Google Maps, yang terbaik adalah FLOAT (10,6) untuk lat dan lng.


di mana Anda mendapatkan informasi ini saya tidak dapat menemukannya? kalau-kalau ada sesuatu yang berubah.
webfacer

1
@webfacer, ada di bagian "Membuat tabel di MySQL" di sini: developers.google.com/maps/documentation/javascript/… misalnya lat FLOAT( 10, 6 ) NOT NULL, lng FLOAT( 10, 6 ) NOT NULL
turrican_34

1
@webfacer, Sepertinya FLOATsintaks sudah tidak digunakan lagi mysql 8.0.17. Mysql sekarang merekomendasikan untuk hanya menggunakan FLOATtanpa parameter presisi dev.mysql.com/doc/refman/8.0/en/numeric-type-overview.html dan dev.mysql.com/doc/refman/5.5/en/floating-point- types.html
turrican_34

7

Kami menyimpan lintang / bujur X 1.000.000 dalam basis data oracle kami sebagai ANGKA untuk menghindari kesalahan pembulatan dengan ganda.

Mengingat bahwa lintang / bujur ke tempat desimal ke-6 adalah akurasi 10 cm yang kami butuhkan. Banyak basis data lain juga menyimpan lat / panjang ke tempat desimal ke-6.


2
Mengalikan dengan sejumlah besar (seperti satu juta) sangat bagus jika Anda memiliki banyak data karena operasi integer (mis. Pengambilan yang diindeks) jauh lebih cepat daripada mengapung.
Kaitlin Duck Sherwood

@KaitlinDuckSherwood - bit adalah bits - Saya tidak mengetahui alasan float 32-bit akan lebih lambat untuk pengambilan (diindeks atau sebaliknya) daripada integer 32-bit. Bahkan matematika mengambang akhir-akhir ini cukup cepat untuk tidak menjadi masalah. Namun demikian, saya setuju dengan komentar untuk menggunakan pengali tersirat dengan integer: ini memaksimalkan presisi yang Anda dapatkan dari 32 bit. Sedikit pembuktian di masa depan saat teknologi meningkat.
ToolmakerSteve

6

Dalam perspektif yang sama sekali berbeda dan lebih sederhana:

  • jika Anda mengandalkan Google untuk menunjukkan peta, spidol, poligon, apa pun, biarkan perhitungan dilakukan oleh Google!
  • Anda menghemat sumber daya di server Anda dan Anda hanya menyimpan garis lintang dan bujur sebagai satu string ( VARCHAR), Misalnya: " -0000.0000001, -0000.000000000000001 " (35 panjang dan jika angka memiliki lebih dari 7 angka desimal maka dibulatkan);
  • jika Google mengembalikan lebih dari 7 angka desimal per angka, Anda bisa mendapatkan data itu disimpan dalam string Anda, kalau-kalau Anda ingin mendeteksi beberapa armada atau mikroba di masa depan ;
  • Anda dapat menggunakan matriks jarak atau pustaka geometri untuk menghitung jarak atau mendeteksi titik di area tertentu dengan panggilan sesederhana ini:google.maps.geometry.poly.containsLocation(latLng, bermudaTrianglePolygon))
  • ada banyak API "sisi-server" yang dapat Anda gunakan (dengan Python , Ruby on Rails , PHP , CodeIgniter , Laravel , Yii , Zend Framework , dll.) yang menggunakan Google Maps API.

Dengan cara ini Anda tidak perlu khawatir tentang pengindeksan angka dan semua masalah lain yang terkait dengan tipe data yang dapat mengacaukan koordinat Anda.


Tidak baik. OP mengatakan dia akan melakukan perhitungan pada pasangan lat / lng - jawaban Anda menghalangi itu
Yarin

4
@Yarin Ini adalah pertanyaan populer di mana beberapa (atau banyak) orang hanya perlu jawaban tentang cara menyimpan koordinat sesuai dengan kebutuhan mereka sendiri (banyak dari mereka mungkin hanya menggunakan peta Google). Downvote Anda menunjukkan bahwa jawaban ini mungkin tidak membantu mereka ... Dengan menyimpan koordinat dalam string, mereka akan tahu persis nilai asli yang diberikan kepada mereka (misalnya: oleh Google) yang akan membantu mereka nanti jika mereka memutuskan untuk mengembangkannya memiliki aplikasi dan melakukan perhitungan pada mereka. Pada saat itu, mereka masih akan memiliki data mentah asli hanya karena mereka tidak mengacaukannya dengan konversi.
Armfoot

4

tergantung pada aplikasi Anda, saya sarankan menggunakan FLOAT (9,6)

kunci spasial akan memberi Anda lebih banyak fitur, tetapi dengan tolok ukur produksi float jauh lebih cepat daripada kunci spasial. (0,01 VS 0,001 dalam AVG)


1
Bisakah Anda memberikan hasil tes Anda dengan detail di sini?
NameNotFoundException

4

MySQL menggunakan ganda untuk semua pelampung ... Jadi, gunakan tipe ganda. Menggunakan float akan menyebabkan nilai bulat yang tidak terduga di sebagian besar situasi


1
MySQL melakukan operasi diDOUBLE . MySQL memungkinkan Anda menyimpan data sebagai 4-byte FLOATatau 8-byte DOUBLE. Jadi, ada kemungkinan akan kehilangan presisi saat menyimpan ekspresi ke dalam FLOATkolom.
Rick James

4

Meskipun tidak optimal untuk semua operasi, jika Anda membuat petak peta atau bekerja dengan banyak marker (titik) dengan hanya satu proyeksi (mis. Mercator, seperti Google Maps dan banyak kerangka peta slippy lainnya harapkan), saya telah menemukan apa Saya menyebut "Sistem Koordinat Luas" untuk menjadi sangat, sangat berguna. Pada dasarnya, Anda menyimpan koordinat x dan y piksel di beberapa cara-diperbesar - Saya menggunakan tingkat zoom 23. Ini memiliki beberapa manfaat:

  • Anda melakukan lat / lng mahal untuk transformasi piksel mercator sekali, bukan setiap kali Anda menangani intinya
  • Mendapatkan koordinat petak dari rekaman yang diberikan tingkat zoom memerlukan satu giliran yang benar.
  • Mendapatkan koordinat piksel dari rekaman membutuhkan satu shift kanan dan satu bitwise AND.
  • Pergeserannya sangat ringan sehingga praktis untuk melakukannya dalam SQL, yang berarti Anda dapat melakukan DISTINCT untuk mengembalikan hanya satu catatan per lokasi piksel, yang akan mengurangi jumlah rekaman yang dikembalikan oleh backend, yang berarti lebih sedikit pemrosesan pada paling depan.

Saya membicarakan semua ini dalam posting blog baru-baru ini: http://blog.webfoot.com/2013/03/12/optimizing-map-tile-generation/


4

Saya sangat terkejut dengan beberapa jawaban / komentar.

Mengapa ada orang yang mau secara sukarela "mengurangi" ketepatan, dan kemudian melakukan perhitungan pada angka yang lebih buruk? Kedengarannya sangat bodoh.

Jika sumber memiliki 64-bit presisi, tentu akan bodoh untuk secara sukarela memperbaiki skala untuk contoh. 6 desimal, dan batasi presisi hingga maksimum 9 digit signifikan (yang terjadi dengan format desimal 9.6 yang umum diusulkan).

Secara alami, seseorang menyimpan data dengan presisi yang dimiliki bahan sumber. Satu-satunya alasan untuk menurunkan presisi adalah ruang penyimpanan yang terbatas.

  • Simpan angka sumber dengan akurasi asli
  • Menyimpan angka yang dihitung dari sumber dalam presisi perhitungan terjadi (mis. Jika kode aplikasi menggunakan ganda, simpan hasilnya sebagai ganda)

Desimal 9,6-format menyebabkan fenomena snap-to-grid. Itu harus menjadi langkah terakhir, jika hal itu benar-benar terjadi.

Saya tidak akan mengundang akumulasi kesalahan ke sarang saya.


2
Karena sebagian besar alat dan aplikasi GPS hanya akurat hingga 6 desimal. Tidak ada gunanya menyimpan data dengan presisi yang lebih besar daripada yang dapat diukur oleh alat gis.stackexchange.com/questions/8650/…
Yarin

1
@ Yarin Ya memang, tetapi Anda berbicara tentang pengukuran dan GPS, yang tidak disebutkan dalam pertanyaan. Pasti ada angka yang lebih akurat. Tapi mari pertimbangkan GPS; katakanlah kumpulan data sumber floats 64-bit, yang sudah mengandung ketidaktepatan. 6 desimal berarti mematahkan garis lintang ke jarak terdekat 11 cm. Karenanya, dengan hanya menyimpan data (dengan 6 desimal) sekarang, Anda membuka kemungkinan ketidaktepatan 22 cm (jika awalnya juga 11 cm). Secara sukarela, mungkin untuk melakukan perhitungan 64-bit itu, sebelum mungkin menyimpan waktu ke-3 - sekarang 33 cm jendela tidak akurat, + -16 cm. Kedengarannya bodoh, imho.
Stormwind

@ Rick James saya mungkin menyimpannya sebagai 64-bit, yaitu. 0.3333333333333333. Kita bicara geodata, kan? "1/3" jarang muncul di alam di mana hal-hal biasanya diukur, dengan ketepatan yang wajar.
Stormwind

4

TL; DR

Gunakan FLOAT (8,5) jika Anda tidak bekerja di NASA / militer dan tidak membuat sistem navi pesawat.


Untuk menjawab pertanyaan Anda sepenuhnya, Anda perlu mempertimbangkan beberapa hal:

Format

  • derajat menit detik : 40 ° 26 ′ 46 ″ N 79 ° 58 ′ 56 ″ W
  • derajat desimal menit : 40 ° 26.767 ′ N 79 ° 58.933 ′ W
  • derajat desimal 1 : 40.446 ° N 79.982 ° W
  • derajat desimal 2 : -32.60875, 21.27812
  • Beberapa format buatan lainnya? Tidak ada yang melarang Anda membuat sistem koordinat home-centric Anda sendiri dan menyimpannya sebagai arah dan jarak dari rumah Anda. Ini bisa masuk akal untuk beberapa masalah khusus yang sedang Anda kerjakan.

Jadi, bagian pertama dari jawabannya adalah - Anda dapat menyimpan koordinat dalam format yang digunakan aplikasi Anda untuk menghindari konversi konstan bolak-balik dan membuat pertanyaan SQL yang lebih sederhana.

Kemungkinan besar Anda menggunakan Google Maps atau OSM untuk menampilkan data Anda, dan GMaps menggunakan format "derajat desimal 2". Jadi akan lebih mudah untuk menyimpan koordinat dalam format yang sama.

Presisi

Kemudian, Anda ingin menentukan presisi yang Anda butuhkan. Tentu saja Anda dapat menyimpan koordinat seperti "-32.608697550570334,21.278081997935146", tetapi apakah Anda pernah peduli tentang milimeter saat navigasi ke titik? Jika Anda tidak bekerja di NASA dan tidak melakukan lintasan satelit atau roket atau pesawat, Anda harus baik-baik saja dengan akurasi beberapa meter.

Format yang umum digunakan adalah 5 digit setelah titik yang memberi Anda akurasi 50cm.

Contoh : ada jarak 1cm antara X, 21.278081 8 dan X, 21.278081 9 . Jadi 7 digit setelah titik memberi Anda presisi 1 / 2cm dan 5 digit setelah titik akan memberikan Anda presisi 1/2 meter (karena jarak minimal antara titik yang berbeda adalah 1m, jadi kesalahan pembulatan tidak boleh lebih dari setengahnya). Untuk sebagian besar keperluan sipil, itu sudah cukup.

format derajat desimal menit (40 ° 26.767 ′ N 79 ° 58.933 ′ W) memberi Anda presisi yang sama persis dengan 5 digit setelah titik

Penyimpanan hemat ruang

Jika Anda memilih format desimal, maka koordinat Anda adalah pasangan (-32.60875, 21.27812). Jelas, 2 x (1 bit untuk tanda, 2 digit untuk derajat dan 5 digit untuk eksponen) sudah cukup.

Jadi di sini saya ingin mendukung Alix Axel dari komentar yang mengatakan bahwa saran Google untuk menyimpannya di FLOAT (10,6) benar-benar ekstra, karena Anda tidak perlu 4 digit untuk bagian utama (karena tanda dipisahkan dan garis lintang terbatas hingga 90 dan bujur dibatasi hingga 180). Anda dapat dengan mudah menggunakan FLOAT (8,5) untuk presisi 1 / 2m atau FLOAT (9,6) untuk presisi 50 / 2cm. Atau Anda bahkan dapat menyimpan lat dan panjang dalam tipe yang terpisah, karena FLOAT (7,5) sudah cukup untuk lat. Lihat referensi tipe float MySQL . Setiap dari mereka akan seperti FLOAT normal dan sama dengan 4 byte.

Biasanya ruang tidak menjadi masalah saat ini, tetapi jika Anda ingin benar-benar mengoptimalkan penyimpanan untuk beberapa alasan (Penafian: jangan melakukan pra-optimasi), Anda dapat memampatkan lat (tidak lebih dari 91.000 nilai + tanda) + panjang (tidak lebih dari 181 000 nilai + tanda) hingga 21 bit yang secara signifikan kurang dari 2xFLOAT (8 byte == 64 bit)


3

Fungsi spasial di PostGIS jauh lebih fungsional (yaitu tidak dibatasi pada operasi BBOX) daripada fungsi spasial MySQL. Lihat ini: tautan teks


1
  1. Garis lintang berkisar dari -90 hingga +90 (derajat), jadi DECIMAL (10, 8) boleh digunakan untuk itu

  2. garis bujur berkisar antara -180 hingga +180 (derajat) sehingga Anda memerlukan DECIMAL (11, 8).

Catatan: Angka pertama adalah jumlah total digit yang disimpan, dan yang kedua adalah angka setelah titik desimal.

Pendeknya: lat DECIMAL(10, 8) NOT NULL, lng DECIMAL(11, 8) NOT NULL



-2

Perhitungan Lat Long membutuhkan ketelitian, jadi gunakan beberapa jenis tipe desimal dan buat ketelitiannya setidaknya 2 lebih tinggi dari angka yang akan Anda simpan untuk melakukan perhitungan matematika. Saya tidak tahu tentang tipe data sql saya tetapi dalam SQL server orang sering menggunakan float atau real bukan desimal dan mendapat masalah karena ini adalah angka yang diperkirakan bukan yang asli. Jadi pastikan tipe data yang Anda gunakan adalah tipe desimal sejati dan bukan tipe desimal mengambang dan Anda harus baik-baik saja.


1
kedua float dan desimal memiliki tempatnya masing-masing. sebagai aturan praktis, float berarti variabel fisik, dan desimal adalah untuk entitas yang dapat dihitung (kebanyakan uang). saya tidak mengerti mengapa Anda lebih suka desimal untuk lat / long
Javier

1
Saya juga berpikir float baik untuk lat / long. Setidaknya pada SQL Server (4bytes, 7 digit).
Dragoljub Ćurčić

Mengambang tidak tepat itu diperkirakan, danau ketepatan dalam waktu yang lama adalah fatal! Ini bisa mengarahkan Anda ke tempat yang sangat berbeda di dunia.
HLGEM

2
Kesalahan maksimum tipe data float cukup rendah sehingga ini seharusnya tidak menjadi masalah. Maksud saya, Anda harus mewaspadai multiplikasi / akumulasi kesalahan dengan kedua implementasi tersebut.
Spidey

@HLGEM - Membulatkan ke beberapa tempat desimal juga membuat Anda berada di tempat berbeda di dunia. Pertanyaannya adalah apakah tempat yang berbeda itu sangat dekat sehingga tidak masalah.
Rick James

-3

A FLOATharus memberi Anda semua presisi yang Anda butuhkan, dan lebih baik untuk fungsi perbandingan daripada menyimpan masing-masing koordinat sebagai string atau sejenisnya.

Jika versi MySQL Anda lebih awal dari 5.0.3, Anda mungkin harus memperhatikan kesalahan perbandingan floating point tertentu .

Sebelum MySQL 5.0.3, kolom DECIMAL menyimpan nilai dengan presisi yang tepat karena mereka direpresentasikan sebagai string, tetapi perhitungan pada nilai DECIMAL dilakukan dengan menggunakan operasi floating-point. Pada 5.0.3, MySQL melakukan operasi DECIMAL dengan ketepatan 64 angka desimal, yang seharusnya bisa menyelesaikan masalah ketidakakuratan paling umum ketika sampai pada kolom DECIMAL


2
Anda memerlukan datatype koordinat lintang / bujur nyata untuk matematika mudah. Bayangkan kenyamanan dari sesuatu yang setara dengan "pilih * dari toko-toko di mana jarak (stores.location, mylocation) <5 miles"
Kirk

1
Belum pernah mendengar tentang perluasan spasial sebelumnya, itu kedengarannya sangat nyaman, setelah sebelumnya bekerja pada aplikasi bawaan yang melakukan sedikit perhitungan terkait geo, harus memeriksanya.
ConroyP

@ConroyP - Tidak. Kutipan itu menunjukkan bahwa DECIMALada (sebelum 5.0.3) kesalahan tertentu karena penggunaan implementasi mengambang.
Rick James
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.