在geodjango(整个表)中按距离排序的效率如何



假设我有以下数据模型:

Person(models.Model):
id       = models.BigAutoField(primary_key=True)
name     = models.CharField(max_length=50)
location = models.PointField(srid=4326)

还假设我有一个查询 Django 后端的应用程序,该应用程序的唯一功能是以分页格式返回从最近到最远排序的注册用户列表。

目前我想到以下查询:

# here we are obtaining all users in ordered form
current_location = me.location
people = Person.objects.distance(current_location).order_by('distance')
# here we are obtaining the first X through pagination
start_index = a
end_index = b
people = people[a:b]

虽然这有效,但它没有我想要的那么快。

我担心这个查询的速度。如果表很广泛(超过 100 万(,那么在通过order_by操作对后续 100 万行进行排序之前,带有 PostGIS 的 Postgres SQL 数据库是否必须计算current_location与数据库中每个location之间的距离?

谁能建议一种更有效的替代方法来根据距离检索和排序附近的用户?

如果您想按距离对该表上的每个条目进行排序,那么它会像预期的那样很慢,并且无能为力(我目前知道这一点和我的知识。

您可以通过执行以下步骤并做出一些假设来提高计算效率:

  1. 对表启用空间索引。要在GeoDjango中执行此操作,请按照文档说明进行操作并将它们适合您的模型:

    注意

    在 PostGIS 中,ST_Distance_Sphere 不限制执行地理距离查询的几何类型。[4] 但是,这些查询可能需要很长时间,因为必须为查询中的每一行动态计算大圆距离。这是因为无法使用传统几何字段上的空间索引。

    为了在 WGS84 距离查询上获得更好的性能,请考虑改用数据库中的地理列,因为它们能够在距离查询中使用其空间索引。您可以通过在字段定义中设置geography=True来告诉GeoDjango使用地理列。

  2. 现在,您可以使用一些逻辑约束来缩小查询范围:

    例如:我的用户不会寻找距离他当前位置超过 50 公里的人。

  3. 使用利用上述空间索引的空间查找dwithin缩小搜索范围,因此它非常快。

  4. 最后,对其余行应用distance顺序。

最终查询可能如下所示:

current_location = me.location
people = People.objects.filter(
location__dwithin=(current_location, D(km=50))
).annotate(
distance=Distance('location', current_location)
).order_by('distance')

PS:与其创建自定义分页尝试,不如利用为 django 视图提供的分页方法更有效:

  • 文档

或者你可以使用 Django Rest Framework 并使用它的分页:

  • 文档和 DRF 分页问答示例

最新更新