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() 函数的用途.实现 ...
随机推荐
- Xcode本地文件 提交svn 的明细
XXXXX.xcscmblueprint 这个文件不用提交svn
- iphone 拨打电话的 两种方法-备
大家想不想在自己的应用中拨打电话呀?打电话可以用openURL:这个API, 如:[[UIApplication sharedApplication] openURL:[NSURL URLWithSt ...
- 单线程Singleton模式的几个要点
1.Singleton模式中的实例构造器可以设置为protected以允许子类派生.2.Singleton模式一般不要支持ICIoneable接口,因为这可能会导致多个对象实例,与Singleton模 ...
- windows 挂载linux nfs
windwos挂载linux主机NFS 启动windos NFS客户端服务: 1. 打开控制面板->程序->打开或关闭windows功能->NFS客户端 勾选NFS客户端,即开启wi ...
- bzoj4034
http://www.lydsy.com/JudgeOnline/problem.php?id=4034 树链剖分. 跟NOI2015的“软件包管理”一模一样..... 河南的爽死了...... #i ...
- Jtree(节点的渲染+资源管理器)(2)
上一次我们建立一个比较简单的资源管理器,这次我们说一下上面的资源管理器的问题,并且得尽量的贴近windows的资源管理器. 这样一个简单的资源管理树就完成了,下面我们说说它的问题: ① 图片和外观和W ...
- NetAnalyzer笔记 之 八 NetAnalyzer2016使用方法(2)
[创建时间:2016-05-06 22:07:00] NetAnalyzer下载地址 在写本篇的时候,NetAnalyzer 3.1版本已经发布,所以本篇就以最新版本的为例继续使用,并且顺带说明一下, ...
- core_cm3文件函数一览
core_cm3是ARM公司推出来的统一规定,这是对下游芯片厂商的统一规定,因此可以再Cortex-M3(CM3)之间进行移植.此文件中定义了一些对特殊功能寄存器的C语言形式的操作,本质上是内敛汇编和 ...
- 使用代码自定义UIView注意一二三
文/CoderAO(简书作者)原文链接:http://www.jianshu.com/p/68b383b129f9著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 当一撮样式一样的视图在 ...
- ASE中的主要数据库
Adaptive Server包括多种类型数据库: 必需数据库. “附加功能”数据库 .例子数据库 .应用数据库 1.必需数据库 master 数据库包含系统表,这些系统表中存储的数据被用来管理,有 ...