GeoDjango触摸功能很慢

时间:2013-11-15 00:07:35

标签: python django postgresql postgis geodjango

首先,这是我的设置:

  • Python 2.7.6
  • Django 1.6
  • PostgreSQL 9.3.1
  • PostGIS 2.1.1

我已将自然地球countriesstates数据集加载到PostGIS中。这是我正在使用的Django模型:

class Location(models.Model):
    name = models.CharField(max_length=255)
    imported_from = models.CharField(max_length=255)
    admin_level = models.CharField(max_length=255, blank=True)
    geometry = models.MultiPolygonField(blank=True, default=None, null=True)
    objects = models.GeoManager() #override the default manager with a GeoManager instance
    parent = models.ForeignKey('self', blank=True, default=None, null=True)

    def __unicode__(self):
            return self.name

    @staticmethod
    def get_countries(continent):
            return Location.objects.filter(parent=continent).order_by('name')

    @staticmethod
    def get_continents():
            return Location.objects.filter(parent=None).order_by('name')

    @staticmethod
    def get_states(country):
            return Location.objects.filter(parent=country).order_by('name')

这应该是相当不言自明的,但需要注意的一点是,这允许一个地点的层次结构(例如,德克萨斯州在美国,在北美)。

我需要获得一组触及其他位置的位置。以下是我在视图中执行此操作的方式:

touching_locations = {x for x in Location.objects.filter(geometry__touches=Location.objects.get(name='LOCATION_NAME').geometry).values_list('name', flat=True)}

这个查询对于某些地方(如安哥拉)来说效果很好,但对于其他一些地方(如美国)来说,它的速度非常慢。我geometry上创建了一个GiST索引,但我没有看到我预期的速度。当我运行美国的查询时,django-debug-toolbar告诉我查询(https://gist.github.com/gfairchild/7476754)需要106260.14毫秒才能完成,这显然是不可接受的。

整个地点表只有4865个条目,所以发生了什么?我是否正确发出此查询?

1 个答案:

答案 0 :(得分:2)

是的,我预计它会很慢,因为你链接的几何体是巨大的:

[[ MULTIPOLYGON - 346 elements, 36054 pts ]]

GiST索引也无济于事,因为CPU会烧掉以确定该点是否在此特定详细多边形内,而不是确定它是否在数千行数据的边界框(bbox)内。请注意,这里是几何和一个重叠几个大洲的bbox:

enter image description here

由于bbox以+ ve经度扭转了日期线,因此它覆盖了欧洲。这意味着如果您要查询欧洲的一个点,它将与美国的bbox相交,而PostGIS可能需要检查这个大的几何体以查看它是否接触到多边形。请参阅R-Tree以了解GiST索引的工作原理,以及为什么具有较少重叠的较小框查询速度最快。


最佳解决方案是使用较小的几何图形,这些几何图形本身具有较少的元素/点,并且通常具有较小的bbox以帮助GiST索引。您提到的“状态”数据集更为理想,因为它们具有有限的地理范围和可能更少的顶点(有助于详细的空间关系查询)。除了自然地球之外,世界范围内确定行政边界的一个非常好的数据集是:http://www.gadm.org

这两个选项都会移动边界并改变“触摸”的含义,因为边界不同,这对“触摸”产生了巨大的影响。请注意,还有其他几个更常见且意味着不同的运算符,例如“intersects”,“contains”和“within”;见https://en.wikipedia.org/wiki/DE-9IM