Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(三)
4.一些实例
1
2
3
4
5
|
>>> hb = Province.objects.get(name__iexact = u "湖北省" ) >>> people = [] >>> for city in hb.city_set. all (): ... people.extend(city.birth. all ()) ... |
1
2
3
4
5
|
>>> hb = Province.objects.prefetch_related( "city_set__birth" ).objects.get(name__iexact = u "湖北省" ) >>> people = [] >>> for city in hb.city_set. all (): ... people.extend(city.birth. all ()) ... |
1
2
3
4
5
6
7
8
9
10
11
12
|
SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.` name ` FROM `QSOptimize_province` WHERE `QSOptimize_province`.` name ` LIKE '湖北省' ; SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.` name `, `QSOptimize_city`.`province_id` FROM `QSOptimize_city` WHERE `QSOptimize_city`.`province_id` IN (1); SELECT `QSOptimize_person`.`id`, `QSOptimize_person`.`firstname`, `QSOptimize_person`.`lastname`, `QSOptimize_person`.`hometown_id`, `QSOptimize_person`.`living_id` FROM `QSOptimize_person` WHERE `QSOptimize_person`.`hometown_id` IN (1, 3); |
1
|
>>> people = list (Person.objects.select_related( "hometown__province" ). filter (hometown__province__name__iexact = u "湖北省" )) |
1
2
3
4
5
6
7
|
SELECT `QSOptimize_person`.`id`, `QSOptimize_person`.`firstname`, `QSOptimize_person`.`lastname`, `QSOptimize_person`.`hometown_id`, `QSOptimize_person`.`living_id`, `QSOptimize_city`.`id`, `QSOptimize_city`.` name `, `QSOptimize_city`.`province_id`, `QSOptimize_province`.`id`, `QSOptimize_province`.` name ` FROM `QSOptimize_person` INNER JOIN `QSOptimize_city` ON (`QSOptimize_person`.`hometown_id` = `QSOptimize_city`.`id`) INNER JOIN `QSOptimize_province` ON (`QSOptimize_city`.`province_id` = `QSOptimize_province`.`id`) WHERE `QSOptimize_province`.` name ` LIKE '湖北省' ; |
1
2
3
4
5
6
7
8
|
+ ----+-----------+----------+-------------+-----------+----+--------+-------------+----+--------+ | id | firstname | lastname | hometown_id | living_id | id | name | province_id | id | name | + ----+-----------+----------+-------------+-----------+----+--------+-------------+----+--------+ | 1 | 张 | 三 | 3 | 1 | 3 | 十堰市 | 1 | 1 | 湖北省 | | 2 | 李 | 四 | 1 | 3 | 1 | 武汉市 | 1 | 1 | 湖北省 | | 3 | 王 | 麻子 | 3 | 2 | 3 | 十堰市 | 1 | 1 | 湖北省 | + ----+-----------+----------+-------------+-----------+----+--------+-------------+----+--------+ 3 rows in set (0.00 sec) |
联用
1
2
3
4
5
6
|
class Order(models.Model): customer = models.ForeignKey(Person) orderinfo = models.CharField(max_length = 50 ) time = models.DateTimeField(auto_now_add = True ) def __unicode__( self ): return self .orderinfo |
1
2
3
4
|
>>> plist = Order.objects.prefetch_related( 'customer__visitation__province' ).get( id = 1 ) >>> for city in plist.customer.visitation. all (): ... print city.province.name ... |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
SELECT `QSOptimize_order`.`id`, `QSOptimize_order`.`customer_id`, `QSOptimize_order`.`orderinfo`, `QSOptimize_order`.` time ` FROM `QSOptimize_order` WHERE `QSOptimize_order`.`id` = 1 ; SELECT `QSOptimize_person`.`id`, `QSOptimize_person`.`firstname`, `QSOptimize_person`.`lastname`, `QSOptimize_person`.`hometown_id`, `QSOptimize_person`.`living_id` FROM `QSOptimize_person` WHERE `QSOptimize_person`.`id` IN (1); SELECT (`QSOptimize_person_visitation`.`person_id`) AS `_prefetch_related_val`, `QSOptimize_city`.`id`, `QSOptimize_city`.` name `, `QSOptimize_city`.`province_id` FROM `QSOptimize_city` INNER JOIN `QSOptimize_person_visitation` ON (`QSOptimize_city`.`id` = `QSOptimize_person_visitation`.`city_id`) WHERE `QSOptimize_person_visitation`.`person_id` IN (1); SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.` name ` FROM `QSOptimize_province` WHERE `QSOptimize_province`.`id` IN (1, 2); |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
+----+-------------+---------------+---------------------+ | id | customer_id | orderinfo | time | +----+-------------+---------------+---------------------+ | 1 | 1 | Info of Order | 2014-08-10 17:05:48 | +----+-------------+---------------+---------------------+ 1 row in set (0.00 sec) +----+-----------+----------+-------------+-----------+ | id | firstname | lastname | hometown_id | living_id | +----+-----------+----------+-------------+-----------+ | 1 | 张 | 三 | 3 | 1 | +----+-----------+----------+-------------+-----------+ 1 row in set (0.00 sec) +-----------------------+----+--------+-------------+ | _prefetch_related_val | id | name | province_id | +-----------------------+----+--------+-------------+ | 1 | 1 | 武汉市 | 1 | | 1 | 2 | 广州市 | 2 | | 1 | 3 | 十堰市 | 1 | +-----------------------+----+--------+-------------+ 3 rows in set (0.00 sec) +----+--------+ | id | name | +----+--------+ | 1 | 湖北省 | | 2 | 广东省 | +----+--------+ 2 rows in set (0.00 sec) |
更好的办法是先调用一次select_related()再调用prefetch_related(),最后再select_related()后面的表
1
2
3
4
|
>>> plist = Order.objects.select_related( 'customer' ).prefetch_related( 'customer__visitation__province' ).get( id = 1 ) >>> for city in plist.customer.visitation. all (): ... print city.province.name ... |
这样只会有3次SQL查询,Django会先做select_related,之后prefetch_related的时候会利用之前缓存的数据,从而避免了1次额外的SQL查询:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
SELECT `QSOptimize_order`.`id`, `QSOptimize_order`.`customer_id`, `QSOptimize_order`.`orderinfo`, `QSOptimize_order`.` time `, `QSOptimize_person`.`id`, `QSOptimize_person`.`firstname`, `QSOptimize_person`.`lastname`, `QSOptimize_person`.`hometown_id`, `QSOptimize_person`.`living_id` FROM `QSOptimize_order` INNER JOIN `QSOptimize_person` ON (`QSOptimize_order`.`customer_id` = `QSOptimize_person`.`id`) WHERE `QSOptimize_order`.`id` = 1 ; SELECT (`QSOptimize_person_visitation`.`person_id`) AS `_prefetch_related_val`, `QSOptimize_city`.`id`, `QSOptimize_city`.` name `, `QSOptimize_city`.`province_id` FROM `QSOptimize_city` INNER JOIN `QSOptimize_person_visitation` ON (`QSOptimize_city`.`id` = `QSOptimize_person_visitation`.`city_id`) WHERE `QSOptimize_person_visitation`.`person_id` IN (1); SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.` name ` FROM `QSOptimize_province` WHERE `QSOptimize_province`.`id` IN (1, 2); |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
+----+-------------+---------------+---------------------+----+-----------+----------+-------------+-----------+ | id | customer_id | orderinfo | time | id | firstname | lastname | hometown_id | living_id | +----+-------------+---------------+---------------------+----+-----------+----------+-------------+-----------+ | 1 | 1 | Info of Order | 2014-08-10 17:05:48 | 1 | 张 | 三 | 3 | 1 | +----+-------------+---------------+---------------------+----+-----------+----------+-------------+-----------+ 1 row in set (0.00 sec) +-----------------------+----+--------+-------------+ | _prefetch_related_val | id | name | province_id | +-----------------------+----+--------+-------------+ | 1 | 1 | 武汉市 | 1 | | 1 | 2 | 广州市 | 2 | | 1 | 3 | 十堰市 | 1 | +-----------------------+----+--------+-------------+ 3 rows in set (0.00 sec) +----+--------+ | id | name | +----+--------+ | 1 | 湖北省 | | 2 | 广东省 | +----+--------+ 2 rows in set (0.00 sec) |
值得注意的是,可以在调用prefetch_related之前调用select_related,并且Django会按照你想的去做:先select_related,然后利用缓存到的数据prefetch_related。然而一旦prefetch_related已经调用,select_related将不起作用。
小结
- 因为select_related()总是在单次SQL查询中解决问题,而prefetch_related()会对每个相关表进行SQL查询,因此select_related()的效率通常比后者高。
- 鉴于第一条,尽可能的用select_related()解决问题。只有在select_related()不能解决问题的时候再去想prefetch_related()。
- 你可以在一个QuerySet中同时使用select_related()和prefetch_related(),从而减少SQL查询的次数。
- 只有prefetch_related()之前的select_related()是有效的,之后的将会被无视掉。
Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(三)的更多相关文章
- 这个贴子的内容值得好好学习--实例详解Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化
感觉要DJANGO用得好,ORM必须要学好,不管理是内置的,还是第三方的ORM. 最最后还是要到SQL.....:( 这一关,慢慢练啦.. 实例详解Django的 select_related 和 p ...
- Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(二)
3. prefetch_related() 对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化.或许你会说,没有一个叫OneToMan ...
- Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(一)
在数据库有外键的时候,使用 select_related() 和 prefetch_related() 可以很好的减少数据库请求的次数,从而提高性能.本文通过一个简单的例子详解这两个函数的作用.虽然Q ...
- 转载 :实例详解Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(一)
在数据库有外键的时候,使用 select_related() 和 prefetch_related() 可以很好的减少数据库请求的次数,从而提高性能.本文通过一个简单的例子详解这两个函数的作用.虽然Q ...
- 实例具体解释Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(二)
这是本系列的第二篇,内容是 prefetch_related() 函数的用途.实现途径.以及用法. 本系列的第一篇在这里 第三篇在这里 3. prefetch_related() 对于多对多字段(Ma ...
- 详解Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化
在数据库有外键的时候,使用 select_related() 和 prefetch_related() 可以很好的减少数据库请求的次数,从而提高性能.本文通过一个简单的例子详解这两个函数的作用. 1. ...
- Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化
引言 在数据库存在外键的其情况下,使用select_related()和prefetch_related()很大程度上减少对数据库的请求次数以提高性能 1.实例准备 模型: from django.d ...
- 转 实例详解Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(三)
这是本系列的最后一篇,主要是select_related() 和 prefetch_related() 的最佳实践. 第一篇在这里 讲例子和select_related() 第二篇在这里 讲prefe ...
- 转 实例具体解释DJANGO的 SELECT_RELATED 和 PREFETCH_RELATED 函数对 QUERYSET 查询的优化(二)
https://blog.csdn.net/cugbabybear/article/details/38342793 这是本系列的第二篇,内容是 prefetch_related() 函数的用途.实现 ...
随机推荐
- Java学习笔记--Collection和Collections的区别
转自 http://pengcqu.iteye.com/blog/492196 比较Collection 和Collections的区别. 1.java.util.Collection 是一个集合 ...
- Android 网络通信框架Volley的简单使用
Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮. Volley提供的功能: JSON,图像等的异步下载: 网络请求的排序(scheduling) 网络请求的优先级处理 ...
- POJ 3525 Most Distant Point from the Sea
http://poj.org/problem?id=3525 给出一个凸包,要求凸包内距离所有边的长度的最小值最大的是哪个 思路:二分答案,然后把凸包上的边移动这个距离,做半平面交看是否有解. #in ...
- 关于Python的3张图
- WebApi接口开发
文档 规范的文档对接口的开发有着至关重要的作用,规范的文档能够使 双方对接口的定义以及接口的参数都有一个明确的概念,便于沟通和联调. 在接口的开发过程中,为了保证传递参数的传递的私密性,参数传输是需要 ...
- java实现矩阵连乘的动态规划
package com.cjs.algorithm; public class DynamicPlan { /** * 此方法用来求解矩阵连乘的最小数乘次数 * * @param p * 传入的要连乘 ...
- JAVA并发实现四(守护线程和线程阻塞)
守护线程 Java中有两类线程:User Thread(用户线程).Daemon Thread(守护线程) 用户线程即运行在前台的线程,而守护线程是运行在后台的线程. 守护线程作用是为其他前台 ...
- poj 1486 Sorting Slides(二分图匹配的查找应用)
Description Professor Clumsey is going to give an important talk this afternoon. Unfortunately, he i ...
- 使用MutationObserver对象封装一个监听DOM生成的函数
(function(win){ 'use strict'; var listeners = []; var doc = win.document; var MutationObserver = win ...
- 【css3+JavaScript】:一个优雅的对话框
实现效果: 演示地址:http://codepen.io/anon/pen/BNjYrR ======2015/5/11====== 优化滚动条(scroll):默认的滚动条太丑,忍不住优化下 ::- ...