我有一个包含+250.000.000行的大型MySQL表,其中存储了不同类型的点和坐标。该表格包含以下列:
的NodeId纬度经度
到目前为止,Lat和Lon字段是FLOAT(10,7)类型,但我正在尝试将它们更改为INT,因为查询此表可能非常慢,即使我已将两个Lat / Lon列编入索引在一起,和Lon专栏。
如果我没弄错的话,MySQL在搜索时只使用一个索引。
我想将两列更改为Integer的原因是因为我会按照Lat对表进行分区,并使用Lon对其进行索引,以使搜索更快。
基本上,我有两个问题,我正在寻找答案:
1。这种方法会使我的边界框查询更快吗?
2。将纬度和经度坐标存储为整数值有什么缺点吗?
编辑:我没有提到的是原始FLOAT值在被存储为整数之前乘以10.000.000。
答案 0 :(得分:1)
您不太可能从
获得搜索性能提升为什么不呢?
如果您正在寻找特定纬度/经度边界框中的点,那么在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)
上的复合索引应该非常好,特别是如果你可以保持搜索半径相当小。
现在,有一个并发症。有了25亿分,您的查询可能就是这样做的。
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/但是,当其中一个元素是地理空间时,您无法创建复合索引。
答案 1 :(得分:1)
这将围绕所有其他技术运行。但是,它需要一些准备工作: http://mysql.rjweb.org/doc.php/latlng
正如该博客指出的那样,乘以10000并存储在MEDIUMINT中可以节省500MB。分辨率为16米/ 52英尺。如果您需要更严格的分辨率,则建议使用INT解决方案(16mm / <1英寸)。 FLOAT,没有不必要的(10,7)给你1.7米/5.6英尺。