需要在GeoDjango中优化PostGIS性能
这是我第一次使用GeoDjango和postGIS。在安装完毕并进行了一些测试后,一切运行正常,但我开始担心当表中的数据行增多时,查询的性能会受到影响。
我在一个几何点中保存了从谷歌地理编码获取的经度和纬度(使用WGS84坐标系统,也就是SRID 4326)。我的问题是,在我的应用中,距离计算是非常常见的操作。我经常需要从一个地标获取附近的地点。几何数学非常复杂,所以即使我有空间索引,未来在一个区域内有超过1000个地点时,查询可能会变得很慢。
那么,有没有办法让这种几何类型的距离计算变得更快呢?有没有人知道可以在Django中使用的库,能够显示包含这些点的谷歌地图?
有没有什么建议可以帮助我加快GeoDjango中的空间查询速度?
3 个回答
如果你的工作区域可以放进一个地图投影里,那这样做会更快,因为这样计算距离时需要的数学运算会少很多。不过,如果你的数据是全球范围的,那就得忍耐一下,使用地理坐标系统。如果你只有美国大陆的数据,可以使用像EPSG:2163这样的投影 http://spatialreference.org/ref/epsg/2163/
你的工作区域越小,使用地图投影得到的结果就会越准确。比如说,美国的州平面投影就是为那些区域性的小范围提供非常准确的投影。而UTM投影则适合更大的国家内部区域。
我正在研究这个话题。根据我找到的信息,使用geopy库得到的坐标是SRID 4326格式的,所以你可以毫无问题地把它们存储在几何字段类型中。下面是一个使用几何的GeoDjango模型示例:
class Landmark(models.Model):
point = models.PointField(spatial_index = True,
srid = 4326,
geography = True)
objects = models.GeoManager()
顺便说一下,传递经度和纬度给PointField时,一定要按照这个顺序。geopy返回的是纬度/经度的坐标,所以你需要把它们调换过来。
为了将一个坐标系中的点转换到另一个坐标系,我们可以使用GEOS和GeoDjango。在这个例子中,我将把一个4326的点转换到著名的谷歌投影900913:
from django.contrib.gis.geos import Point
punto = Point(40,-3)
punto.set_srid(900913)
punto.transform(4326)
punto.wkt
Out[5]: 'POINT (0.0003593261136478 -0.0000269494585230)'
这样我们就可以在投影系统中存储坐标,这样在数学计算上会有更好的性能。 如果想在管理界面上显示谷歌地图上的点,我们可以参考这篇很棒的文章。
我决定继续使用地理类型,如果将来需要提高性能,我会进行转换。