如何将Django三级关联模型迭代的3次SELECT查询优化至2次及以下?
优化Django链式外键查询至1次SELECT
针对你的模型结构,从Country出发使用嵌套prefetch_related会产生3次查询的原因是:
- 第一次查询所有
Country - 第二次查询所有关联的
State - 第三次查询所有关联的
City
要将查询次数优化到1次,可以换查询起点,从最底层的City模型发起查询,利用select_related一次性拉取所有关联对象,再在Python层面重组层级结构:
实现步骤
1. 单次查询获取所有关联数据
City到State、State到Country都是正向外键关联,使用select_related('state__country')可以通过SQL JOIN一次性拉取所有关联数据,仅产生1次SELECT查询:
cities = City.objects.select_related('state__country').all()
2. 在Python层面重组层级结构
用字典将查询结果整理为Country → State → [City]的层级,方便迭代输出:
from collections import defaultdict # 构建层级映射 country_state_cities = defaultdict(lambda: defaultdict(list)) for city in cities: country = city.state.country state = city.state country_state_cities[country][state].append(city) # 迭代输出 for country, states in country_state_cities.items(): for state, city_list in states.items(): for city in city_list: print(country, state, city)
备选方案(2次查询)
如果坚持从Country出发,可以通过自定义Prefetch对象优化,将查询次数减少至2次:
from django.db.models import Prefetch # 预获取每个State对应的City集合 state_prefetch = Prefetch( 'state_set', queryset=State.objects.prefetch_related('city_set') ) # 查询Country并关联预获取的State+City数据 countries = Country.objects.prefetch_related(state_prefetch).all() # 迭代输出 for country in countries: for state in country.state_set.all(): for city in state.city_set.all(): print(country, state, city)
这种方式会执行2次查询:一次查Country,一次批量查所有关联的State和City。
内容的提问来源于stack exchange,提问作者Super Kai - Kazuya Ito
相关产品推荐
相关产品推荐

