简体   繁体   English

GeoDjango的触控功能很慢

[英]GeoDjango touches function is slow

First off, here's my setup: 首先,这是我的设置:

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

I have loaded up the Natural Earth countries and states datasets into PostGIS. 我已将“自然地球” 国家 /地区和州的数据集加载到PostGIS中。 Here's the Django model I'm using: 这是我正在使用的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')

This should be fairly self-explanatory, but an important thing to note is that this allows for a hierarchy of locations (eg, Texas is in the US, which is in North America). 这应该是不言自明的,但是要注意的重要一点是,这允许对位置进行分层(例如,德克萨斯州在美国,而在北美)。

I need to get a set of locations that touch some other location. 我需要获取一组与其他位置相关的位置。 Here's how I'm doing this in the view: 在视图中,这是我的操作方式:

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

This query works just fine for some locations (like Angola), but it's abysmally slow for some others (like the US). 该查询在某些位置(例如安哥拉)工作得很好,但在其他一些位置(例如美国)却非常慢。 I do have a GiST index created on geometry , but I'm not seeing the speed I expected. 确实geometry创建了GiST索引,但是没有看到预期的速度。 When I run the query for the US, django-debug-toolbar tells me that the query ( https://gist.github.com/gfairchild/7476754 ) takes a whopping 106260.14 ms to complete, which is obviously unacceptable. 当我在美国运行查询时,django-debug-toolbar告诉我该查询( https://gist.github.com/gfairchild/7476754 )需要花费106260.14毫秒才能完成,这显然是不可接受的。

The entire locations table only has 4865 entries, so what's going on? 整个locations表只有4865个条目,这是怎么回事? Am I issuing this query right? 我发出这个查询对吗?

Yes, I'd expect it to be slow since the geometry that you linked to is massive: 是的,我希望它会很慢,因为您链接到的几何非常庞大:

[[ MULTIPOLYGON - 346 elements, 36054 pts ]]

A GiST index won't help either, since the CPU burning away to determine if the point is within this specific detailed multipolygon, rather then determining if it is within a bounding box (bbox) of thousands of rows of data. GiST索引也无济于事,因为CPU忙于确定该点是否在此特定的详细多多边形内,而不是确定该点是否在数千行数据的边界框(bbox)内。 Note, here is the geometry and a bbox that overlaps a few continents: 请注意,这是与几大洲重叠的几何图形和bbox:

在此处输入图片说明

Since the bbox warps over the date-line with +ve longitudes, it covers Europe. 由于bbox在带有+ ve经度的日期线上弯曲,因此它覆盖了欧洲。 This means if you are querying a point in Europe, it will intersect the bbox for the United States, and PostGIS may need to check this large geometry to see if it is touches the polygon. 这意味着,如果您要查询欧洲的某个点,它将与美国的bbox相交,并且PostGIS可能需要检查这个较大的几何图形,以查看它是否接触了多边形。 See R-Tree to get an understanding of how the GiST index works, and why smaller boxes with fewer overlaps query fastest. 请参阅R-Tree ,以了解GiST索引的工作原理,以及为什么重叠少的小盒子查询最快。


The best solution is to use smaller geometries, which inherently have fewer elements/points and will normally have smaller bboxes to help the GiST index. 最好的解决方案是使用较小的几何体,它们固有地具有较少的元素/点,并且通常具有较小的bbox可以帮助GiST索引。 The "states" dataset you mentioned is more ideal, since they have limited geographic extents and probably fewer vertices (helps detailed spatial relation query). 您提到的“状态”数据集更为理想,因为它们的地理范围有限并且顶点可能更少(有助于详细的空间关系查询)。 Besides Natural Earth, a really good dataset for determining administrative boundaries world wide is: http://www.gadm.org 除了“自然地球”外, http//www.gadm.org还有一个非常好的数据集,可以用来确定全球范围内的行政边界

Both these options will move the boundaries and change what "touches" means, since the boundaries are different and this make a huge difference for "touches". 这两个选项都将移动边界并更改“触摸”的含义,因为边界是不同的,这对“触摸”产生了巨大的影响。 Note that there are several other operators that are more common and mean different things, such as "intersects", "contains", and "within"; 请注意,还有其他一些更常见且表示不同含义的运算符,例如“相交”,“包含”和“内部”。 see https://en.wikipedia.org/wiki/DE-9IM 参见https://en.wikipedia.org/wiki/DE-9IM

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM