Enlem / boylamı bir MySQL veritabanında saklarken kullanılacak ideal veri türü nedir?


432

Enlem / boylam çiftlerinde hesaplamalar yapacağımı göz önünde bulundurarak, hangi veri tipinin bir MySQL veritabanı ile kullanılması en uygunudur?


1
Bu bağlantıyı çok yararlı buldum: howto-use-mysql-spatial-ext.blogspot.com/2007/11/… Biraz daha eski olabilir, ancak örnekler de dahil olmak üzere tam bir açıklama içerir.
madc

Buradaki çoğu insan ne olduğunu anlamıyor. Uygulama kodu bir sayıya dokunduğunda , kişi iki katına çıkarsa (en çok yapar), sayı en fazla çift kesinlike dönüşür . Bir milyon ondalık sayı ile bile depolamak hiçbir işe yaramaz. Sınırlı sayıda ondalık (örneğin 6) ile saklamak , bu hassasiyetin bir kısmını yok eder ve veritabanına her yeniden yazıldığında biriken bir hata ekler . Bir çift, potansiyel olarak tüm ondalık sayılarla yaklaşık 16 önemli sayı taşır. 10 tanesinin kazınması zamanla birikmiş bir hata yaratır. Bu nedenle "kayan nokta" dır. Devam.
Stormwind

Devam: Bir rakam harici bir kaynaktan alındığı gibi, değiştirilmemiş olarak ve ilk kez - kaynak malzeme olarak saklanırken 6 ondalık değer olabilir. Ancak, bir kez bile bir hesaplama yapar ve tekrar saklarsanız, belirli bir ondalık biçimi uygulayarak hassasiyetinin bir kısmını kaldırmak aptaldır . Hesaplamanın yalnızca sunucu içinde gerçekleştirilmesi farklı olabilir (sunucu dahili olarak iki kattan başka bir şey kullanıyor olabilir veya olmayabilir) ve uygulama hesaplamasında iki kattan daha kötü sayısal gösterimler kullanmak, depolama hassasiyeti ihtiyacını eşit derecede azaltır.
Stormwind

Devam: Eğer sunucu iddia edilen "9.6" (ki eğer bilmiyorum) rağmen daha yüksek bir hassasiyetle numarayı saklar , o zaman tüm bu hiçbir şey önemli değildir ve biçimi tamamen kolaylık meselesi - hassas sorunlarla yapmak. Ancak sunucu aslında bu formatla 6 ondalık hassasiyete herhangi bir sayı yuvarlarsa sürpriz olmaz.
Stormwind

Devam: Son olarak: Lat, lon'lar için 6. ondalık sayı bir ca'ya yapışmakla ilgilidir . 11 santimetre ızgara. 6 ondalık ile her okunduğunda (dokunduğunda), yeniden hesapladığında ve kaydettiğinde, yeni bir yakalama olacaktır (= biriken hata). Tüm hatalar aynı yönde ilerlerse, büyük bir hata olacaktır. Üzerinde geçici çarpmalar gerçekleştiriliyorsa (örn. Ölçek büyütme, sonra çıkarma ve ölçeklendirme), daha da büyüyebilir. İyi bir rason olmadan hassaslığı hurdaya atmayın!
Stormwind

Yanıtlar:


161

MySQL'in mekansal uzantılarını GIS ile kullanın .


25
Örneklere veya bunlarla en iyi şekilde nasıl başlayacağınıza dair başka bir bağlantınız var mı?
Codebeef

6
MYSQL Spatial iyi bir seçenektir, ancak yine de önemli sınırlar ve uyarılar vardır (6'dan itibaren). Lütfen aşağıdaki cevabımı görün ...
James Schek

1
@James Schek haklı. Ayrıca, MySQL tüm hesaplamalarını öklid geometrisi kullanarak yapar, bu nedenle lat / lng için gerçek dünya kullanım durumunu temsil etmez.
mkuech

Bilginize; Mysql, yalnızca * .myisam tabloları, yani ISAM motoru ile uzamsal dizini destekler. Bağlantı: dev.mysql.com/doc/refman/5.0/en/creating-spatial-indexes.html
PodTech.io


150

Google, Google Haritalar ile örnek bir "Mağaza Bulucu" uygulaması için PHP / MySQL çözümünü bitirmeye başlıyor. Bu örnekte lat / lng değerlerini "10,6" uzunluğunda "Float" olarak saklarlar

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


11
Google, FLOAT spesifikasyonunun nasıl çalıştığını açıkça anlamıyor: FLOAT(10,6)koordinatın tamsayı kısmı için 4 basamak bırakır. Ve hayır, işaret sayılmaz - bu (un) imzalı öznitelikten gelir.
Alix Axel

2
Ancak, [0, 180] 'in ayrılmaz parça değerleri olarak depolamanız gerekiyorsa, o zaman yeterli olacaktır, değil mi?
Hrvoje Golcic

37
@AlixAxel Bence Google ne yaptığını biliyor. O belirtiyor Çünkü: " . Google Maps'in mevcut yakınlaştırma yetenekleri ile yalnızca ondalık sonra kesinlik 6 hanesini gerektiğinde Yani alanlar, örneğin ondalık önce en fazla 4 basamak ondalık sonra 6 basamak depolamak, artı sağlayacak - 123.456789 derece ". İmzasız işaretlenirse, desen 1234.567890 olacaktır . Yani sorun yok.
1.44mb

16
@AlixAxel Dizideki sayıları sayıyor; gerçek bir koordinat kullanmıyor ...
Andrew Ellis

8
DoubleLaravel için veri tipini kullanma
FooBar

134

Temel olarak konumlarınız için ihtiyacınız olan hassasiyete bağlıdır. DOUBLE kullanarak 3,5 nm hassasiyete sahip olacaksınız. DECIMAL (8,6) / (9,6) 16 cm'ye iner. YÜZER 1.7m ...

Bu çok ilginç tablonun daha eksiksiz bir listesi var: 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

Bu yardımcı olur umarım.


2
Yazıların içeriğine odaklanmış yapıcı, ayrıntılı bir yorum yazmam gerekiyor, bu yüzden Rick James'in web sitesinden sağlanan doğruluk tablosunu gözlemlerken, "köpek üzerinde pire" çözünürlük açıklamasında hafifçe eğlendim ve Kudos'a layık hissettim. Teknik olarak konuşursak, bu iki adres arasındaki mesafeyi ölçmek için koordinatları saklarken hangi veri tipinin kullanılacağına karar vermemde bana yardımcı olan yararlı bir tasvirdi, bu da @Simon, paylaştığınız için teşekkür ederim.
Sam_Butler

FWIW, bu bağlantının "SMALLINT ölçeklendirilmiş" kullanımı korkunç derecede verimsiz. Oğuzhan'ın cevabı , ondalık noktadan sonra 7 basamaklı uzun / lat uzunluğunu 4 baytlık imzalı bir int'de saklamanın harika bir yoludur . Küçük boyutta (4B) büyük hassasiyet (~ 1 cm).
ToolmakerSteve

74

MySQL'in Uzamsal Uzantıları en iyi seçenektir, çünkü uzamsal operatörlerin ve indekslerin tam listesine sahipsiniz. Bir uzamsal dizin, mesafeye dayalı hesaplamaları çok hızlı bir şekilde yapmanızı sağlar. 6.0'dan itibaren, Uzamsal Uzantı'nın hala eksik olduğunu lütfen unutmayın. MySQL Spatial'ı bırakmıyorum, sadece bu konuda çok ilerlemeden önce tuzakları bilmenizi sağlıyorum.

Noktalarla ve yalnızca MESAFE işleviyle kesinlikle uğraşıyorsanız, bu iyi. Çokgenler, Çizgiler veya Tamponlu Noktalar ile herhangi bir hesaplama yapmanız gerekiyorsa, "ilgili" işlecini kullanmadığınız sürece uzamsal işleçler kesin sonuçlar vermez. 21.5.6'nın üst kısmındaki uyarıya bakın . İçerir, içeride veya kesişmeler gibi ilişkiler kesin geometri şeklini değil MBR'yi kullanır (yani Elips bir Dikdörtgen gibi ele alınır).

Ayrıca, MySQL Spatial'daki mesafeler ilk geometrinizle aynı birimlerdedir. Bu, Ondalık Derece kullanıyorsanız, mesafe ölçümleriniz Ondalık Derece cinsindendir. Bu, ekvatordan furthur alırken kesin sonuçlar almayı çok zorlaştıracaktır.


26
Yeniden ifade etme: MySQL Uzamsal Uzantıları, dünyanın yüzeyindeki enlem / boylam ile temsil edilen noktalar arasındaki büyük daire mesafelerini hesaplamak için uygun değildir. Mesafe fonksiyonları, vb. Sadece kartezyen, düzlemsel, koordinatlarda yararlıdır.
O. Jones

71

ARINC424'ten inşa edilmiş bir navigasyon veritabanı için bunu yaptığımda, test ve koda tekrar baktığımda adil bir miktar yaptım, bir DECIMAL (18,12) kullandım (Firebird olduğu için bir NUMERIC (18,12)).

Şamandıralar ve çiftler o kadar kesin değildir ve çok kötü bir şey olabilecek yuvarlama hatalarına neden olabilir. Sorunları olan herhangi bir gerçek veri bulup bulmadığımı hatırlayamıyorum - ancak bir şamandıra veya çiftte doğru bir şekilde saklanamamanın sorunlara neden olabileceğinden oldukça eminim

Mesele şu ki, derece veya radyan kullanırken değerlerin aralığını biliyoruz - ve kesirli kısım en fazla rakama ihtiyaç duyuyor.

MySQL Mekansal Uzantıları onlar takip çünkü iyi bir alternatiftir OpenGIS Geometri Modeli . Onları kullanmadım çünkü veritabanımı taşınabilir tutmam gerekiyordu.


3
Teşekkür ederim, bu yardımcı oldu. 2008'den 8 yıl önce olduğunu fark ederek tüm bu soruları ve cevapları okumak garip geliyor.
aexl

1
@TheSexiestManinJamaica - IEEE 754-1985'ten önce bilgisayar kayan nokta donanımı kaotikti. Makinede bile a*beşit olmayan b*a(bazı değerler için) vardı. Birçok örnek biraz gibi vardı: 2+2 = 3.9999. Standart çok fazla karışıklık yarattı ve neredeyse her donanım ve yazılım parçası tarafından 'hızla' kabul edildi. Dolayısıyla, bu tartışma sadece 2008'den beri değil, yüzyılın üçte biri için geçerlidir.
Rick James

42

İhtiyacınız olan hassasiyete bağlıdır.

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

Gönderen: http://mysql.rjweb.org/doc.php/latlng

Özetle:

  • Mevcut en hassas seçenek DOUBLE.
  • En sık kullanılan tiptir DECIMAL(8,6)/(9,6).

İtibariyle MySQL 5.7 , kullanmayı mekansal veri türleri özel olarak ise, (SDT) POINTtek bir koordinat depolamak için. 5.7'den önce, SDT dizinleri desteklemez (tablo türü MyISAM olduğunda 5.6 hariç).

Not:

  • POINTSınıf kullanırken , koordinatları saklamak için kullanılan argümanların sırası olmalıdır POINT(latitude, longitude).
  • Bir uzamsal dizin oluşturmak için özel bir sözdizimi vardır .
  • SDT kullanmanın en büyük yararı, Mekansal Analiz Fonksiyonlarına erişebilmenizdir , örneğin iki nokta arasındaki mesafeyi hesaplamak ( ST_Distance) ve bir noktanın başka bir alanda ( ST_Contains) bulunup bulunmadığını belirlemek .

2
Bir önceki cevabın yapıştırılmış kısmını kopyalarsınız ve o tabloyu yaratan adamın tavsiye etmediği bir şeyi "özetlersiniz" : «BÖLME nasıl? MySQL çok seçici. FLOAT / DOUBLE çıktı. DECIMAL çıktı. Yani, biraz çamurla sıkışıp kaldık. Esasen, Lat / Lng'yi bir miktar INT boyutuna dönüştürmeli ve PARTITION BY RANGE'ı kullanmalıyız. » VE «FLOAT'ta 24 önemli bit vardır; DOUBLE 53 var. (BÖLME ile çalışmazlar, ancak tamlık için dahil edilirler. Genellikle insanlar DOUBLE'ı ne kadar fazla kullanıldığını ve ne kadar yer kapladığını fark etmeden kullanırlar .) »Yazdığınız SDT parçasını bırakın.
Armfoot

1
@Armfoot Düzenleme zamanına bakarsanız, benden kopyalanan diğer cevap budur. Önemli değil: Stack Overflow'u "gelecek için notlar" ın daha çok görüyorum.
Gajus

1
Hayır sizden kopyalamadı, sadece 2014'te referans verdiği bağlantıdan yaptığınız gibi masayı yapıştırdı (yayınınız 2015'ten). Btw, Sanırım Mekansal Veri Türlerini bağladığınızda "Özel" i yanlış yazdınız . Yazdığınız bu bölüm CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;, James'in belirttiği gibi, SDT sınırlamaları gibi bazı örnekler ve uyarılar eklerseniz , belki de yanıtınız diğer insanlara yardımcı olmak için daha özlü ve kesin olacaktır. ..
Armfoot

@Gajus - İkinizin belgemi bulmasından onur duyuyorum! (Hayır, bir pire ne kadar büyük olduğunu bilmiyorum, ama birinin dikkatini çekeceğini hissettim.)
Rick James

POINT sınıfını kullanırken, koordinatların saklanması için bağımsız değişkenlerin sırası POINT (boylam / X, enlem / Y) olmalıdır.
AndreyP


19

Kullanım DECIMAL(8,6)enlem (90 -90 derece) ve DECIMAL(9,6)boylam (180 -180 derece) için. Çoğu uygulama için 6 ondalık basamak uygundur. Negatif değerlere izin vermek için her ikisi de "imzalı" olmalıdır.


DECIMALtürü, floor/ceilkabul edilmeyen finansal hesaplamalar içindir . Düz FLOATönemli ölçüde daha iyi performans gösterir DECIMAL.
Kondybas

1
@Kondybas - Bir veritabanındaki ana maliyet satır getirme olduğundan, kayan sayı ile ondalık arasındaki performans farkı endişe yaratmamalıdır.
Rick James

14

Google Haritalar'a göre, en iyisi lat ve lng için FLOAT (10,6).


bu bilgiyi nereden buldum onu ​​bulamıyorum? bir şeylerin değişmesi durumunda.
webfacer

1
@webfacer, Buradaki "MySQL'de tablo oluşturma" bölümünde: developers.google.com/maps/documentation/javascript/… eg lat FLOAT( 10, 6 ) NOT NULL, lng FLOAT( 10, 6 ) NOT NULL
turrican_34

1
@webfacer, Görünüşe göre FLOATsözdizimi kaldırıldı mysql 8.0.17. MySQL şimdi sadece kullanımına önerir FLOATherhangi hassas parametreler olmadan dev.mysql.com/doc/refman/8.0/en/numeric-type-overview.html ve dev.mysql.com/doc/refman/5.5/en/floating-point- types.html
turrican_34

7

Enlem / boylam X 1.000.000'i çift katlı hatalardan kaçınmak için oracle veritabanımızda NUMARALAR olarak saklıyoruz.

6. ondalık yere enlem / boylam 10 cm doğruluk tüm ihtiyaç vardı göz önüne alındığında. Diğer birçok veritabanı da 6. ondalık basamağa kadar enlem / boylam depolar.


2
Çok fazla veriye sahipseniz, çok sayıda (milyon gibi) ile çarpmak harikadır, çünkü tamsayı işlemleri (örn. Endeksli geri alma) kayan noktalardan çok daha hızlıdır.
Kaitlin Duck Sherwood

@KaitlinDuckSherwood - bitler bit - 32 bitlik bir float alımı için 32-bit tamsayıdan daha yavaş (endeksli veya başka) yavaş olmasının herhangi bir nedeninin farkında değilim. Bugünlerde kayan matematik bile sorun olmayacak kadar hızlı. Yine de, zımni çarpanı bir tamsayı ile kullanma yorumuna katılıyorum: 32 bitten elde ettiğiniz hassasiyeti en üst düzeye çıkarır. Teknoloji geliştikçe biraz geleceğe hazır.
ToolmakerSteve

6

Tamamen farklı ve daha basit bir perspektifte:

Bu şekilde sayıları endeksleme ve koordinatlarınızı bozabilecek veri türleriyle ilişkili diğer tüm sorunlar hakkında endişelenmenize gerek kalmaz.


İyi değil. OP, lat / lng çiftlerinde hesaplamalar yapacağını söyledi - yanıtlarınız bunu engelliyor
Yarin

4
@Yarin Bu, birkaç kişinin (veya bir çok kişinin) koordinatları kendi ihtiyaçlarına göre nasıl depolayacağına dair bir cevaba ihtiyaç duyduğu popüler bir sorudur (birçoğu sadece Google haritalarını kullanabilir). Downvote'unuz bu cevabın onlara yardımcı olamayabileceğini gösteriyor ... Koordinatları bir dizede saklayarak, kendilerine sağlanan orijinal değerleri (ör: Google tarafından) tam olarak bilecekler; kendi app ve onlara hesaplamalar yapmak. O zamanlar, yalnızca dönüşümle uğraşmadıkları için orijinal ham verilere sahip olacaklar.
Armfoot

4

Uygulamaya bağlı olarak FLOAT (9,6) kullanmanızı öneririm

mekansal anahtarlar size daha fazla özellik verecektir, ancak üretim ölçütlerinde şamandıralar mekansal anahtarlardan çok daha hızlıdır. (AVG'de 0,01 VS 0,001)


1
Lütfen test sonucunuzu burada ayrıntılarla verebilir misiniz?
NameNotFoundException

4

MySQL tüm şamandıralar için double kullanır ... Yani double tipi kullanın. Float kullanımı çoğu durumda öngörülemeyen yuvarlak değerlere yol açar


1
MySQL, içinde işlem yaparDOUBLE . MySQL, verileri 4 bayt veya 8 bayt olarak depolamanızı sağlar . Dolayısıyla, bir ifadeyi bir sütuna depolarken hassasiyet kaybı olması muhtemeldir . FLOATDOUBLEFLOAT
Rick James

4

Tüm işlemler için en uygun olmasa da, harita döşemeleri yapıyorsanız veya yalnızca bir projeksiyonla çok sayıda işaretleyici (nokta) ile çalışıyorsanız (örneğin, Mercator, Google Haritalar ve diğer birçok kaygan harita çerçevesi beklenir), ne buldum "Geniş Koordinat Sistemi" ni gerçekten çok kullanışlı buluyorum. Temel olarak, x ve y piksel koordinatlarını bir şekilde yakınlaştırılmış olarak saklarsınız - Yakınlaştırma düzeyi 23'ü kullanırım. Bunun birkaç faydası vardır:

  • Noktayı her ele aldığınızda pahalı lat / lng - mercator piksel dönüşümünü bir kez yaparsınız
  • Yakınlaştırma düzeyi verildiğinde döşeme koordinatını bir kayıttan almak bir sağ kaydırma yapar.
  • Bir kayıttan piksel koordinatını almak bir sağa kaydırma ve bir bit yönünde VE alır.
  • Vardiyalar o kadar hafiftir ki, bunları SQL'de yapmak pratiktir, yani piksel konumu başına yalnızca bir kayıt döndürmek için bir DISTINCT yapabilirsiniz, bu da arka ucun döndürdüğü sayı kayıtlarını azaltacaktır, bu da başlangıç ​​aşaması.

Tüm bunları son blog yazısında konuştum: http://blog.webfoot.com/2013/03/12/optimizing-map-tile-generation/


4

Bazı cevaplar / yorumlar beni çok şaşırttı.

Neden dünyadaki herkes hassasiyeti gönüllü olarak "ön azaltmaya" ve daha sonra daha kötü sayılar üzerinde hesaplamalar yapmaya istekli olur? Sonuçta aptalca geliyor.

Kaynak 64 bit hassasiyete sahipse, ölçeği gönüllü olarak düzeltmek aptalca olur. 6 ondalık basamak ve hassasiyeti maksimum 9 anlamlı basamakla sınırlandırın (yaygın olarak önerilen ondalık 9.6 biçiminde olur).

Doğal olarak, veriler kaynak materyalin sahip olduğu hassasiyetle saklanır. Hassasiyeti azaltmanın tek nedeni sınırlı depolama alanı olacaktır.

  • Kaynak rakamlarını orijinal doğrulukta saklayın
  • Kaynaktan hesaplanan rakamları hesaplamanın gerçekleştiği kesinlikte saklayın (örneğin, uygulama kodu iki katına çıkarsa, sonuçları iki katına saklayın)

Ondalık 9.6 biçimi ızgaraya yapışan bir fenomene neden olur. Eğer gerçekleşecekse, bu son adım olmalıdır.

Birikmiş hataları yuvama davet etmem.


2
Çünkü çoğu GPS aracı ve uygulaması sadece 6 ondalık basamağa kadar doğrudur. Verileri, hangi araçların ölçebileceğinden daha büyük bir hassasiyetle saklamak anlamsız gis.stackexchange.com/questions/8650/…
Yarin

1
@Yarin Evet, ama soruda belirtilmeyen ölçümler ve GPS hakkında konuşuyorsunuz. Kesinlikle daha doğru rakamlar var. Ancak GPS'i ele alalım; 64-bit float halihazırda bir yanlışlık içeren bir kaynak veri kümesi diyelim. 6 ondalık sayı, enlemi yaklaşık 11 santimetreye yakınlaştırmak anlamına gelir. Bu nedenle, sadece verileri (6 ondalık sayıyla) şimdi saklayarak, potansiyel 22 cm'lik bir yanlışlık için açıyorsunuz (orijinal olarak 11 cm ise). Gönüllü olarak, belki de 64 bit hesaplama yapmak için, belki 3. kez saklamadan önce - şimdi 33 cm yanlışlık penceresi, + -16 cm. Aptal gibi geliyor, imho.
Stormwind

@Rick James 64-bit olarak depolayacağım, yani. ,3333333333333333. Coğrafi veriler konuşuyoruz, değil mi? "1/3" nadiren makul bir hassasiyetle işlerin normal olarak ölçüldüğü bir yapıda görülür.
Stormwind

4

TL; DR

NASA / askeriyede çalışmıyor ve uçak navi sistemleri yapmıyorsanız FLOAT (8,5) kullanın.


Sorunuzu tam olarak cevaplamak için birkaç şeyi göz önünde bulundurmanız gerekir:

Biçim

  • derece dakika saniye : 40 ° 26 ′ 46 ″ N 79 ° 58 ′ 56 ″ W
  • derece ondalık dakika : 40 ° 26.767 ′ N 79 ° 58.933 ′ W
  • ondalık derece 1 : 40.446 ° K 79.982 ° W
  • ondalık derece 2 : -32.60875, 21.27812
  • Başka bir ev yapımı format? Kimse kendi ev merkezli koordinat sisteminizi oluşturmanızı ve evinize rota ve mesafe olarak kaydetmenizi yasaklar. Bu, üzerinde çalıştığınız bazı sorunlar için anlamlı olabilir.

Cevabın ilk kısmı şu olacaktır: koordinatları uygulamanızın kullandığı formatta saklayabilirsiniz, sürekli dönüşümleri önlemek için ileri geri ve daha basit SQL sorguları yapabilirsiniz.

Büyük olasılıkla verilerinizi görüntülemek için Google Haritalar veya OSM kullanırsınız ve GMaps'lar "ondalık derece 2" biçimini kullanır. Böylece koordinatları aynı formatta saklamak daha kolay olacaktır.

Hassas

Ardından, ihtiyacınız olan hassasiyeti tanımlamak istersiniz. Tabii ki "-32.608697550570334,21.278081997935146" gibi koordinatları saklayabilirsiniz, ancak noktaya navigasyon yaparken hiç milimetre aldınız mı? NASA'da çalışmıyorsanız ve uydular, roketler veya uçak yörüngeleri yapmıyorsanız, birkaç metre hassasiyetle iyi olmalısınız.

Yaygın olarak kullanılan biçim, noktalardan sonra 5 basamaktır ve bu size 50 cm doğruluk sağlar.

Örnek : X, 21.278081 8 ve X, 21.278081 arasında 1 cm mesafe vardır 9 . Noktadan sonra 7 basamak size 1 / 2cm hassasiyet verir ve noktadan sonra 5 basamak size 1/2 metre hassasiyet verir (çünkü farklı noktalar arasındaki minimum mesafe 1m olduğundan, yuvarlama hatası bunun yarısından fazla olamaz). Çoğu sivil amaç için yeterli olmalıdır.

derece ondalık dakika biçimi (40 ° 26.767 ′ N 79 ° 58.933 ′ W) noktadan sonra 5 basamakla tam olarak aynı hassasiyeti verir

Yerden tasarruf sağlayan depolama

Ondalık biçim seçtiyseniz, koordinatınız bir çifttir (-32.60875, 21.27812). Açıkçası, 2 x (işaret için 1 bit, derece için 2 basamak ve üs için 5 basamak) yeterli olacaktır.

Burada Alix Axel'yi FLOAT'ta (10,6) saklamak için Google önerisinin gerçekten ekstra olduğunu söyleyerek yorumlardan destek almak istiyorum , çünkü ana bölüm için 4 basamağa ihtiyacınız yok (işaret ayrıldığından ve enlem sınırlı olduğundan) ve boylam 180 ile sınırlıdır). 1 / 2m hassasiyet için FLOAT (8,5) veya 50 / 2cm hassasiyet için FLOAT (9,6) kullanabilirsiniz. Ya da lat ve uzunları ayrı tiplerde saklayabilirsiniz, çünkü FLOAT (7,5) lat için yeterlidir. Bkz. MySQL şamandıra türleri referansı . Bunlardan herhangi biri normal FLOAT gibi ve yine de 4 bayta eşit olacak.

Genellikle alan günümüzde bir sorun değildir, ancak depolamayı bir nedenden dolayı gerçekten optimize etmek istiyorsanız (Feragat: ön optimizasyon yapma), lat (91 000 değer + işaretten fazla değil) + uzun (hayır 181 000'den fazla değer + işareti), 2xFLOAT'tan (8 bayt == 64 bit) önemli ölçüde daha az olan 21 bite kadar


3

PostGIS'deki uzamsal işlevler, MySQL uzamsal işlevlerden çok daha işlevseldir (yani BBOX işlemleriyle kısıtlanmamıştır). Şuna göz atın: bağlantı metni


1
  1. Enlemler -90 ila +90 (derece) arasında değişir, bu nedenle DECIMAL (10, 8) bunun için uygundur

  2. boylamlar -180 ila +180 (derece) arasında değişir, bu nedenle DECIMAL'a ihtiyacınız vardır (11, 8).

Not: İlk sayı, saklanan toplam basamak sayısı ve ikincisi ondalık noktadan sonraki sayıdır.

Kısacası: lat DECIMAL(10, 8) NOT NULL, lng DECIMAL(11, 8) NOT NULL



-2

Lat Long hesaplamaları hassasiyet gerektirir, bu nedenle bir tür ondalık türü kullanın ve hassasiyeti matematik hesaplamaları yapmak için saklayacağınız sayıdan en az 2 daha yüksek yapın. Benim sql veri türleri hakkında bilmiyorum ama SQL sunucusunda insanlar genellikle ondalık yerine float veya gerçek kullanın ve bunlar gerçek olmayan değil tahmin numaraları olduğundan belaya olsun. Bu nedenle, kullandığınız veri türünün kayan ondalık tür değil, gerçek bir ondalık tür olduğundan emin olun ve iyi olmalısınız.


1
hem şamandıra hem de ondalık türlerin yeri vardır. genel bir kural olarak, değişkenler fiziksel değişkenler anlamına gelir ve ondalık sayılar sayılabilir varlıklar içindir (çoğunlukla para). neden lat / long için ondalık basamak tercih edeceğinizi anlamıyorum
Javier

1
Ben de şamandıra lat / uzun için iyi olduğunu düşünüyorum. En azından SQL Server'da (4 bayt, 7 basamak).
Dragoljub Ćurčić

Şamandıra tam olarak tahmin edilmiyor, enlemdeki gölün kesinliği ölümcül! Sizi dünya üzerinde tamamen farklı bir noktaya yönlendirebilir.
HLGEM

2
Kayan noktalı veri türlerindeki maksimum hata, bunun bir sorun olmaması için yeterince düşüktür. Yani, her iki uygulamada da hata çarpımı / birikiminin farkında olmalısınız.
Spidey

@HLGEM - Birkaç ondalık basamağa yuvarlamak da sizi dünyanın farklı bir noktasına götürür . Soru şu ki, farklı noktanın o kadar yakın olup olmadığı önemli değil.
Rick James

-3

A FLOAT, ihtiyacınız olan tüm hassasiyeti vermeli ve karşılaştırma işlevleri için her bir koordinatı bir dize veya benzeri olarak depolamaktan daha iyi olmalıdır.

MySQL sürümünüz 5.0.3'ten eskiyse, ancak belirli kayan nokta karşılaştırma hatalarına dikkat etmeniz gerekebilir .

MySQL 5.0.3'ten önce, DECIMAL sütunları, dizeler olarak temsil edildikleri için değerleri kesin bir şekilde depolar, ancak DECIMAL değerleri üzerinde hesaplamalar kayan nokta işlemleri kullanılarak yapılır. 5.0.3 itibariyle, MySQL, DECIMAL sütunları söz konusu olduğunda en yaygın yanlışlık sorunlarını çözmesi gereken 64 ondalık basamak hassasiyetiyle DECIMAL işlemleri gerçekleştirir


2
Kolay matematik için gerçek bir enlem / boylam koordinat veri tipine ihtiyacınız vardır. Uzaklığın (mağazalar.konum, yer değiştirme) <5 mil "olan mağazalardan" seç * "gibi bir şeyin rahatlığını düşünün
Kirk Strauser

1
Daha önce mekansal uzantıları duymamıştı, bu çok uygun görünüyor, daha önce coğrafi olarak biraz hesaplama yapan dev bir uygulama üzerinde çalışmış, kontrol etmeliyiz.
ConroyP

@ConroyP - Hayır. Bu alıntı, DECIMALkayan uygulamanın kullanımı nedeniyle ( 5.0.3'ten önce) bazı hataların bulunduğuna işaret ediyor .
Rick James
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.