Enlem / boylam çiftlerinde hesaplamalar yapacağımı göz önünde bulundurarak, hangi veri tipinin bir MySQL veritabanı ile kullanılması en uygunudur?
Enlem / boylam çiftlerinde hesaplamalar yapacağımı göz önünde bulundurarak, hangi veri tipinin bir MySQL veritabanı ile kullanılması en uygunudur?
Yanıtlar:
MySQL'in mekansal uzantılarını GIS ile kullanın .
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
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.
Double
Laravel için veri tipini kullanma
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.
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.
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.
a*b
eş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.
İ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:
DOUBLE
.DECIMAL(8,6)/(9,6)
.İtibariyle MySQL 5.7 , kullanmayı mekansal veri türleri özel olarak ise, (SDT) POINT
tek bir koordinat depolamak için. 5.7'den önce, SDT dizinleri desteklemez (tablo türü MyISAM olduğunda 5.6 hariç).
Not:
POINT
Sınıf kullanırken , koordinatları saklamak için kullanılan argümanların sırası olmalıdır POINT(latitude, longitude)
.ST_Distance
) ve bir noktanın başka bir alanda ( ST_Contains
) bulunup bulunmadığını belirlemek .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. ..
Bu wiki makalesine dayanarak http://en.wikipedia.org/wiki/Decimal_degrees#Accuracy , MySQL içindeki uygun veri türü, boylam ve enlemi ayrı alanlarda saklamak için Ondalıktır (9,6).
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.
DECIMAL
türü, floor/ceil
kabul edilmeyen finansal hesaplamalar içindir . Düz FLOAT
önemli ölçüde daha iyi performans gösterir DECIMAL
.
Google Haritalar'a göre, en iyisi lat ve lng için FLOAT (10,6).
lat FLOAT( 10, 6 ) NOT NULL,
lng FLOAT( 10, 6 ) NOT NULL
FLOAT
sözdizimi kaldırıldı mysql 8.0.17
. MySQL şimdi sadece kullanımına önerir FLOAT
herhangi 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
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.
Tamamen farklı ve daha basit bir perspektifte:
VARCHAR
), Örn .: " -0000.0000001, -0000.000000000000001 " (35 uzunluk ve bir sayı 7 ondalık basamağa sahipse yuvarlanır);google.maps.geometry.poly.containsLocation(latLng, bermudaTrianglePolygon))
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.
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)
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
DOUBLE
. 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 . FLOAT
DOUBLE
FLOAT
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:
Tüm bunları son blog yazısında konuştum: http://blog.webfoot.com/2013/03/12/optimizing-map-tile-generation/
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.
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.
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
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
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
Enlemler -90 ila +90 (derece) arasında değişir, bu nedenle DECIMAL (10, 8) bunun için uygundur
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
SQL Server için Float veri türü kullanmanızı öneririm.
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.
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
DECIMAL
kayan uygulamanın kullanımı nedeniyle ( 5.0.3'ten önce) bazı hataların bulunduğuna işaret ediyor .