假设我有以下数据模型:
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 万个),带有 PostGIS 的 Postgres SQL 数据库是否必须计算表之间的距离?current_location
和每一个location
在对随后的 100 万行进行排序之前,先在数据库中进行排序order_by
手术?
谁能建议一种更有效的替代方法来根据距离检索和排序附近的用户?
如果您想按距离对该表上的每个条目进行排序,那么它会像预期的那样慢,并且无能为力(我目前知道并且我的知识。)!
您可以按照以下步骤并做出一些假设来提高计算效率:
-
Enable 空间索引在你的桌子上。要在 GeoDjango 中执行此操作,请遵循文档说明并将它们适合您的模型:
Note
在 PostGIS 中,ST_Distance_Sphere 不限制执行地理距离查询的几何类型。[4]但是,这些查询可能需要很长时间,因为必须为查询中的每一行动态计算大圆距离。这是因为传统几何字段上的空间索引无法使用。
为了在 WGS84 距离查询上获得更好的性能,请考虑使用地理专栏相反,因为他们能够在距离查询中使用空间索引。您可以通过设置告诉 GeoDjango 使用地理列geography=True
在你的字段定义中。
-
现在您可以使用一些逻辑约束来缩小查询范围:
Ex:我的用户不会寻找距离他当前位置超过 50 公里的人。
使用缩小搜索范围dwithin利用上述的空间查找空间索引,因此速度相当快。
最后应用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')
P.S:使用 django 视图提供的分页方法比创建自定义分页尝试更有效:
或者您可以使用 Django Rest Framework 并使用它的分页:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)