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() 函数的用途.实现 ...
随机推荐
- ScrollView嵌套listview 时根据内容动态设置listview高度
public static void setListViewHeightBasedOnChilds(ListView listView){ ListAdapter listAdapter = list ...
- 设置ListView每条数据之间的间隔
1:如果不需要分割线可以在xml布局文件中ListView下设置XML属性: android:divider="#00000000" android:dividerHeight=& ...
- 自制单片机之十三……时钟IC_DS1302
在网上看了很久,发现初学者最有兴趣的就是DS1302时钟电路,也很自然,它是个做出来就让你觉得最实用的电路了,但实际上制做上并不简单,首先你要让你的显示部分(不管是数码管还是LCD)调试通过.然后把D ...
- Cmake find_package()相关
也就是find_package可以帮助直接找到库的头文件和库文件(.lib,dll .etc) References: http://blog.csdn.net/dbzhang800/article/ ...
- B树叶子节点split
一.B-Tree索引的分裂 1. 创建测试表 SQL> create table split_tab (id number, name varchar2(100)); 表已创建. SQL> ...
- ios论坛
http://developer.cocoachina.com/ 讨论区:http://www.cocoachina.com/bbs/ http://bbs.9ria.com/forum-58-1.h ...
- 关于selenium中的sendKeys()隔几秒发送一个字符
看一下你的IEDriverServer.exe是不是64位的,我也遇到了这样的问题,换成32位的IEDriverServer.exe,瞬间速度快了
- 把第三方的exe程序嵌入C#界面上
public partial class eTerm_Form : WinFormsUI.Docking.DockContent{public eTerm_Form(){InitializeCompo ...
- C#中dynamic、ExpandoObject 的正确用法
原文地址:http://www.cnblogs.com/qiuweiguo/archive/2011/08/03/2125982.html dynamic是FrameWork4.0的新特性.dynam ...
- HTML浅识
HTML相关======= ## 认识网页 *web标准(w3c三种标准):结构标准 -->html 表现标准 -->css 行为标准 -->js **浏览器和服务器:浏览器发送报文 ...