2013-11-15 37 views
1

首先,這裏是我的設置: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 ms才能完成,這顯然是不可接受的。

整個位置表只有4865個條目,所以發生了什麼?我發出這個查詢是否正確?

回答

2

是的,我希望它是緩慢的,因爲你鏈接到幾何是巨大的:

[[ MULTIPOLYGON - 346 elements, 36054 pts ]] 

要旨指數將沒有幫助的,因爲CPU燒掉,以確定該點在這個特定的詳細多層多邊形內,而不是確定它是否在數千行數據的邊界框(bbox)內。注意,這裏是幾何形狀和重疊幾大洲BBOX:

enter image description here

由於BBOX扭曲在日線與+已經經度,它涵蓋了歐洲。這意味着如果您在歐洲查詢某個點,它將與美國的bbox相交,並且PostGIS可能需要檢查此大型幾何圖形以查看它是否觸及了多邊形。請參閱R-Tree以瞭解GiST索引的工作原理,以及爲什麼較小重疊查詢的查詢速度最快。


最佳解決方法是使用更小的幾何形狀,其固有地具有更少的元件/分,而且一般具有較小的bboxes幫助主旨索引。您提到的「州」數據集更爲理想,因爲它們具有有限的地理範圍和可能較少的頂點(有助於詳細的空間關係查詢)。除了自然地球,確定世界範圍內的行政邊界的一個非常好的數據集是:http://www.gadm.org

這兩個選項都會移動邊界並更改「接觸」的含義,因爲邊界不同,這會對「接觸」產生巨大影響」。請注意,還有其他幾種更常見且意味着不同內容的其他操作符,例如「交叉點」,「包含」和「內部」;看到https://en.wikipedia.org/wiki/DE-9IM

+0

這是一個非常好的解釋,並不是我所期望的。另一個解決方案是,我們可以簡單地修剪夏威夷/阿拉斯加的外部點,使bbox更小。如果我們去了州數據集,這個問題實際上並沒有解決,因爲夏威夷/阿拉斯加的Bbox仍然會環繞。 – Geoff