我想在前端下拉列表中显示不同的用户城市。为此,我进行了一个数据库查询,该查询city_name
与表不同,City
但仅获取用户所在的城市。
像下面这样的东西适用于小尺寸的桌子,但如果桌子尺寸为 1000 万User
,则需要很长时间。User
这些用户的不同城市仍然是〜100。
class City(models.Model):
city_code = models.IntegerField(unique=True)
city_name = models.CharField(max_length=256)
class User(models.Model):
city = models.ForeignKey('City', to_field='city_code')
现在我尝试搜索不同的城市名称:
City.objects.filter().values_list('city__city_name').distinct()
这在 PostgreSQL 上转换为:
SELECT DISTINCT "city"."city_name"
FROM "user"
LEFT OUTER JOIN "city"
ON ("user"."city_id" = "city"."city_code");
时间:9760.302 毫秒
这清楚地表明 PostgreSQL 没有使用 'user'.'city_id' 上的索引。我还在这里阅读了一个解决方法,其中涉及编写一个自定义 SQL 查询,该查询以某种方式利用索引。
我尝试使用上面的查询找到不同的 'user'.'city_id',结果实际上速度非常快。
WITH
RECURSIVE t(n) AS
(SELECT min(city_id)
FROM user
UNION
SELECT
(SELECT city_id
FROM user
WHERE city_id > n order by city_id limit 1)
FROM t
WHERE n is not null)
SELECT n
FROM t;
时间:79.056 毫秒
但是现在我发现很难将其合并到我的 Django 代码中。我仍然认为这是一种在代码中添加自定义查询的技巧。但对我来说更大的担忧是列名可以是完全动态的,我不能在代码中硬编码这些列名(例如 city_id 等)。
#original_fields could be a list from input, like ['area_code__district_code__name']
dataset_klass.objects.filter().values_list(*original_fields).distinct()
使用自定义查询至少需要将字段名称以“__”作为分隔符并处理第一部分。但这对我来说似乎是一个糟糕的黑客行为。
我该如何改进呢?
PS。该City
User
示例仅用于解释该场景。语法可能不正确。