1

私は、iOS デバイスで指定されたPlacemarksを MySQL バックエンドに保存する小さなアプリに取り組んでいます。デバイスが新しいPlacemarkを保存すると、DB に INSERT され、新しく生成された ID がクライアントに送り返されます。別のデバイスが同じPlacemarkを保存しようとした場合、サーバーはそれが DB に既に存在することを認識する必要があり、新しい ID を INSERT して生成する代わりに、その Placemark の既存の ID をクライアントに送り返す必要があります。

2目印が同一である場合、目印は同じです。

  • 名前
  • 緯度
  • 経度

したがって、サーバーは、送信された Placemark が既に存在するかどうかを識別しようとします。

SELECT id FROM Placemark WHERE 名前=x、緯度=y、経度=x

  • iOS ではlatitude、によって報告されlongitudeた度数とタイプです。CLLocationDegrees<CoreLocation>
  • MySQL ではlatitudelongitude次のように定義されています。DOUBLE


問題:
座標を保存するときに精度が失われます。たとえば、次
latidudeのように50.09529561485427保存されます。50.0952956148543
longitude-122.9893130423316-122.989313042332

質問:
MySQL で異なるデータ型を使用して、各座標をそのまま保存することはできますか?

ノート:

  • 座標を保存TEXTできVARCHARないSELECT placemarks coordinates BETWEEN x AND y
  • 移植性に問題があるため、また、私の理解では、キーとして使用すると空間データ型が非常に遅くなるため、MySQL の空間拡張機能を使用できません (また、私のユース ケースでは座標による SELECT が必要です)。

どんな助けでも大歓迎

4

2 に答える 2

3

Actually further testing revealed the following curious outcome: the precision is lost when the DB driver binds the data to the query statement, and before the data is actually inserted into the DB.

This has the following interesting consequence: The precision seems to be lost in an identical manner even when I bind keys to my subsequent search queries, and therefore almost "accidentally" the correct result is returned. That is, the key (coordinates) is stored incorrectly, and then subsequent selects also convert query keys incorrectly, but in a matching manner, and therefore the record is found. Given that the conversions due to precision loss are always performed on the same platform (the server), it's probably safe to leave as is?? Or maybe not, perhaps a future migration exercise (i.e., due to scaling) will make the rounding errors apparent.

Yawar's pointer led me to MySQL's manual which explains that floating point numbers can be stored without loss of precision as DECIMAL:

"Exact-value numeric literals have an integer part or fractional part, or both. They may be signed" http://dev.mysql.com/doc/refman/5.0/en/precision-math-decimal-changes.html

Given that the existing solution seems to work, the question then becomes, is it better to keep the DB data type DOUBLE, or switch to DECIMAL?

Storage:
Latitude has range from -90 to +90, and iOS seems to use precision of 14 decimals
Longitude has range from -180 to +180, which leaves precision of 13 decimals on iOS

That means we need:
Latitude : DECIMAL(16,14), which takes less the 8 bytes of storage (4 bytes for each pack of 9d)
Longitude: DECIMAL(16,13), also requiring less than 8 bytes of storage

In contrast, a column of type DOUBLE requires 8 bytes of storage.

Speed (arithmetic):
Floating point arithmetic will almost always be materially faster because it is supported natively by the hardware

Speed (searches):
I believe index of DECIMAL vs index of DOUBLE have a very comparable runtime.

Conclusion:
Switching to DECIMAL eliminates the precision errors and also reduces storage requirements, at an arithmetic performance penalty which is negligible in this use case.

于 2013-02-19T06:08:48.800 に答える
0

緯度と経度を double として格納する代わりに、1000000 を掛けて、整数に変換して格納します。もちろん、アプリで読み返す必要がある場合は、1000000.0 で割ります。

これにより、目印に十分な精度 (0.000001º) が与えられ、浮動小数点変換と精度の問題が解消され、使用するスペースがわずかに少なくなります。これを自分のデータ (SQL ではなくバイナリ) で使用し、MicroDegrees と呼びます。

于 2013-02-21T05:26:15.970 に答える