1

首先,这是我的设置:

  • Python 2.7.6
  • 姜戈 1.6
  • PostgreSQL 9.3.1
  • 地理信息系统 2.1.1

我已将自然地球国家和州的数据集加载到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)}

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

整个位置表只有 4865 个条目,这是怎么回事?我发出这个查询对吗?

4

1 回答 1

2

是的,我希望它会很慢,因为您链接到的几何图形很大:

[[ MULTIPOLYGON - 346 elements, 36054 pts ]]

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

在此处输入图像描述

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


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

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

于 2013-11-15T03:06:44.053 回答