我有一个包含 +250.000.000 行的大型 MySQL 表,我在其中存储不同类型的点和坐标。该表包含以下列:
NodeId Lat Lon
到目前为止,Lat 和 Lon 字段都是 FLOAT(10,7) 类型,但我正在尝试将它们更改为 INT,因为查询此表可能非常慢,即使我已经为 Lat/Lon 列编制了索引在一起,而 Lon 列本身。
如果我没记错的话,MySQL 在搜索时只使用单个索引。
我想将两列更改为 Integer 的原因是,例如,我会按 Lat 对表进行分区,并按 Lon 对其进行索引,以加快搜索速度。
基本上,我有两个问题正在寻找答案:
1. Would this kind of approach make my bounding box queries faster?
2. Are there any drawbacks of storing Latitude and Longitude coordinates as Integer values?
编辑:我没有提到的是原始 FLOAT 值在存储为整数之前乘以 10.000.000。
最佳答案
你不太可能从任何一个中获得搜索性能的改进
- 分区表或
- 将纬度/经度的数据类型从 FLOAT 更改为 INTEGER。
为什么不呢?
- 存储的数据量对于 FLOAT 和 INTEGER 是相同的:32 位。
- FLOAT 为 GPS 分辨率数据提供了足够的精度。如果您知道并关心 UTM 和 Lambert 投影之间的差异,请使用 DOUBLE。
- 索引范围搜索适用于 FLOAT、DOUBLE 和 INTEGER。
- 如果对表进行分区,则需要做额外的工作来防止索引范围搜索命中大量分区。命中大量分区会使搜索变慢。
如果您要在特定的纬度/经度边界框中查找点,在 MySQL 中将类似于以下内容:
SET @radius := 50; /* 50km */
SET @units := 111.045l /* kilometers per degree */
SET @lat := 40.7484;
SET @lon := ,-73.9857;
SELECT ...
WHERE table.latitude
BETWEEN @lat - (@radius / @units )
AND @lat + (@radius / @units )
AND table.longitue
BETWEEN @lon - (@radius / @units * COS(RADIANS(@lat))))
AND @lon + (@radius / @units * COS(RADIANS(@lat))))
注意这采用的形式
table.latitude BETWEEN constant AND constant
AND table.longitude BETWEEN constant AND constant
这两项中的第一项是对 latitude
列的直接范围扫描。如果它被索引,即使它是 FLOAT
数据类型也很快。 (latitude, longitude)
上的复合索引应该非常好,特别是如果您可以将搜索半径保持在相当小的范围内。
现在,有一个并发症。有了 2.5 亿个点,您的查询可能会执行类似这样的操作。
table.point_type = constant
AND table.latitude BETWEEN constant AND constant
AND table.longitude BETWEEN constant AND constant
在这种情况下,您需要在 (point_type, latitude, longitude)
上使用复合索引,以便查询可以做正确的事情。对于这么大的表,您确实需要了解您的查询才能正确设置索引。
最后,根据您拥有的点数,您可以考虑使用 MySQL 的地理空间扩展来进行位置搜索。这是写在这里。 http://www.plumislandmedia.net/mysql/using-mysqls-geospatial-extension-location-finder/但是,当其中一个元素是地理空间元素时,您无法创建复合索引。
关于mysql - 在 mysql 中将纬度/经度存储为整数有什么缺点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28444316/