(十)从十三次查询减少到两次
上面的脚本后半段逐本读取用户名与标签。六本书先用一次 SELECT 取得,每本访问未加载的 owner 再查一次,每本访问标签再查一次,共 1+6+6=13 次。
select_related("owner") 将单值外键通过 JOIN 放进书籍查询;prefetch_related("tags") 再用一次查询取出这些书的全部标签关联,按编号分配回各个对象。结果相同,查询数变成 2。
select_related 适合外键这类单值关系,多对多集合用 prefetch_related。模板里 book.tags.all 可以使用已经预取的结果;若改为每本执行另一份 filter 或单列查询,就需要重新检查是否又发出了 SQL。这里统计的是书籍查询段,不把登录会话等请求查询混进比较。
优化从实际查询次数与结果开始,相关工具见 Django 数据库访问优化。