对于多对多字段(ManyToManyField)和一对多字段, 可以使用prefetch_related()来进行优化

prefetch_related()和select_related()的设计目的很相似,都是为了减少SQL查询的数量,但是实现的方式不一样。后者是通过JOIN语句,在SQL查询内解决问题。但是对于多对多关系,使用SQL语句解决就显得有些不太明智,因为JOIN得到的表将会很长,会导致SQL语句运行时间的增加和内存占用的增加。若有n个对象,每个对象的多对多字段对应Mi条,就会生成Σ(n)Mi 行的结果表。prefetch_related()的解决方法是,分别查询每个表,然后用Python处理他们之间的关系。继续以上边的例子进行说明,如果我们要获得张三所有去过的城市,使用prefetch_related()应该是这么做:

zhangs = Person.objects.prefetch_related('visitation').get(firstname=u"张",lastname=u"三")
>>> for city in zhangs.visitation.all() :
...   print city

上述代码触发的SQL查询如下:

SELECT `QSOptimize_person`.`id`, `QSOptimize_person`.`firstname`,
`QSOptimize_person`.`lastname`, `QSOptimize_person`.`hometown_id`, `QSOptimize_person`.`living_id`
FROM `QSOptimize_person`
WHERE (`QSOptimize_person`.`lastname` = '三'  AND `QSOptimize_person`.`firstname` = '张');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);

第一条SQL查询仅仅是获取张三的Person对象,第二条比较关键,它选取关系表`QSOptimize_person_visitation`中`person_id`为张三的行,然后和`city`表内联(INNER JOIN 也叫等值连接)得到结果表。

  1. +----+-----------+----------+-------------+-----------+
  2. | id | firstname | lastname | hometown_id | living_id |
  3. +----+-----------+----------+-------------+-----------+
  4. | 1 | 张 | 三 | 3 | 1 |
  5. +----+-----------+----------+-------------+-----------+
  6. 1 row in set (0.00 sec)
  7. +-----------------------+----+-----------+-------------+
  8. | _prefetch_related_val | id | name | province_id |
  9. +-----------------------+----+-----------+-------------+
  10. | 1 | 1 | 武汉市 | 1 |
  11. | 1 | 2 | 广州市 | 2 |
  12. | 1 | 3 | 十堰市 | 1 |
  13. +-----------------------+----+-----------+-------------+
  14. 3 rows in set (0.00 sec)

显然张三武汉、广州、十堰都去过。

又或者,我们要获得湖北的所有城市名,可以这样:

  1. >>> hb = Province.objects.prefetch_related('city_set').get(name__iexact=u"湖北省")
  2. >>> for city in hb.city_set.all():
  3. ... city.name
  4. ...

触发的SQL查询:

  1. SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name`
  2. FROM `QSOptimize_province`
  3. WHERE `QSOptimize_province`.`name` LIKE '湖北省' ;
  4. SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`
  5. FROM `QSOptimize_city`
  6. WHERE `QSOptimize_city`.`province_id` IN (1);

得到的表:

+----+-----------+
| id | name      |
+----+-----------+
|  1 | 湖北省    |
+----+-----------+
1 row in set (0.00 sec) +----+-----------+-------------+ | id | name | province_id | +----+-----------+-------------+ | 1 | 武汉市 | 1 | | 3 | 十堰市 | 1 | +----+-----------+-------------+ 2 rows in set (0.00 sec)

我们可以看见,prefetch使用的是 IN 语句实现的。这样,在QuerySet中的对象数量过多的时候,根据数据库特性的不同有可能造成性能问题。

使用方法

*lookups 参数

prefetch_related()在Django < 1.7 只有这一种用法。和select_related()一样,prefetch_related()也支持深度查询,例如要获得所有姓张的人去过的省:

  1. >>> zhangs = Person.objects.prefetch_related('visitation__province').filter(firstname__iexact=u'张')
  2. >>> for i in zhangs:
  3. ... for city in i.visitation.all():
  4. ... print city.province
  5. ...

触发的SQL:

  1. SELECT `QSOptimize_person`.`id`, `QSOptimize_person`.`firstname`,
  2. `QSOptimize_person`.`lastname`, `QSOptimize_person`.`hometown_id`, `QSOptimize_person`.`living_id`
  3. FROM `QSOptimize_person`
  4. WHERE `QSOptimize_person`.`firstname` LIKE '张' ;
  5. SELECT (`QSOptimize_person_visitation`.`person_id`) AS `_prefetch_related_val`, `QSOptimize_city`.`id`,
  6. `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id` FROM `QSOptimize_city`
  7. INNER JOIN `QSOptimize_person_visitation` ON (`QSOptimize_city`.`id` = `QSOptimize_person_visitation`.`city_id`)
  8. WHERE `QSOptimize_person_visitation`.`person_id` IN (1, 4);
  9. SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name`
  10. FROM `QSOptimize_province`
  11. WHERE `QSOptimize_province`.`id` IN (1, 2);

获得的结果:

+----+-----------+----------+-------------+-----------+
| id | firstname | lastname | hometown_id | living_id |
+----+-----------+----------+-------------+-----------+
|  1 | 张        | 三 | 3 | 1 | | 4 | 张 | 六 | 2 | 2 | +----+-----------+----------+-------------+-----------+ 2 rows in set (0.00 sec) +-----------------------+----+-----------+-------------+ | _prefetch_related_val | id | name | province_id | +-----------------------+----+-----------+-------------+ | 1 | 1 | 武汉市 | 1 | | 1 | 2 | 广州市 | 2 | | 4 | 2 | 广州市 | 2 | | 1 | 3 | 十堰市 | 1 | +-----------------------+----+-----------+-------------+ 4 rows in set (0.00 sec) +----+-----------+ | id | name | +----+-----------+ | 1 | 湖北省 | | 2 | 广东省 | +----+-----------+ 2 rows in set (0.00 sec)

值得一提的是,链式prefetch_related会将这些查询添加起来,就像1.7中的select_related那样。

要注意的是,在使用QuerySet的时候,一旦在链式操作中改变了数据库请求,之前用prefetch_related缓存的数据将会被忽略掉。这会导致Django重新请求数据库来获得相应的数据,从而造成性能问题。这里提到的改变数据库请求指各种filter()、exclude()等等最终会改变SQL代码的操作。而all()并不会改变最终的数据库请求,因此是不会导致重新请求数据库的。

举个例子,要获取所有人访问过的城市中带有“市”字的城市,这样做会导致大量的SQL查询:

  1. plist =Person.objects.prefetch_related('visitation')
  2. [p.visitation.filter(name__icontains=u"市")for p in plist]

因为数据库中有4人,导致了2+4次SQL查询:

  1. SELECT `QSOptimize_person`.`id`, `QSOptimize_person`.`firstname`, `QSOptimize_person`.`lastname`,
  2. `QSOptimize_person`.`hometown_id`, `QSOptimize_person`.`living_id`
  3. FROM `QSOptimize_person`;
  4. SELECT (`QSOptimize_person_visitation`.`person_id`) AS `_prefetch_related_val`, `QSOptimize_city`.`id`,
  5. `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`
  6. FROM `QSOptimize_city`
  7. INNER JOIN `QSOptimize_person_visitation` ON (`QSOptimize_city`.`id` = `QSOptimize_person_visitation`.`city_id`)
  8. WHERE `QSOptimize_person_visitation`.`person_id` IN (1, 2, 3, 4);
  9. SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`
  10. FROM `QSOptimize_city`
  11. INNER JOIN `QSOptimize_person_visitation` ON (`QSOptimize_city`.`id` = `QSOptimize_person_visitation`.`city_id`)
  12. WHERE(`QSOptimize_person_visitation`.`person_id` = 1 AND `QSOptimize_city`.`name` LIKE '%市%' );
  13. SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`
  14. FROM `QSOptimize_city`
  15. INNER JOIN `QSOptimize_person_visitation` ON (`QSOptimize_city`.`id` = `QSOptimize_person_visitation`.`city_id`)
  16. WHERE (`QSOptimize_person_visitation`.`person_id` = 2 AND `QSOptimize_city`.`name` LIKE '%市%' );
  17. SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`
  18. FROM `QSOptimize_city`
  19. INNER JOIN `QSOptimize_person_visitation` ON (`QSOptimize_city`.`id` = `QSOptimize_person_visitation`.`city_id`)
  20. WHERE (`QSOptimize_person_visitation`.`person_id` = 3 AND `QSOptimize_city`.`name` LIKE '%市%' );
  21. SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`
  22. FROM `QSOptimize_city`
  23. INNER JOIN `QSOptimize_person_visitation` ON (`QSOptimize_city`.`id` = `QSOptimize_person_visitation`.`city_id`)
  24. WHERE (`QSOptimize_person_visitation`.`person_id` = 4 AND `QSOptimize_city`.`name` LIKE '%市%' );

众所周知,QuerySet是lazy的,要用的时候才会去访问数据库。运行到第二行Python代码时,for循环将plist看做iterator,这会触发数据库查询。最初的两次SQL查询就是prefetch_related导致的。

虽然已经查询结果中包含所有所需的city的信息,但因为在循环体中对Person.visitation进行了filter操作,这显然改变了数据库请求。因此这些操作会忽略掉之前缓存到的数据,重新进行SQL查询。

但是如果有这样的需求了应该怎么办呢?在Django >= 1.7,可以通过下一节的Prefetch对象来实现,如果你的环境是Django < 1.7,可以在Python中完成这部分操作。

  1. plist = Person.objects.prefetch_related('visitation')
  2. [[city for city in p.visitation.all() if u"市" in city.name] for p in plist]
Prefetch对象

在Django >= 1.7,可以用Prefetch对象来控制prefetch_related函数的行为。

1.一个Prefetch对象只能指定一项prefetch操作。
2.Prefetch对象对字段指定的方式和prefetch_related中的参数相同,都是通过双下划线连接的字段名完成的。
3.可以通过 queryset 参数手动指定prefetch使用的QuerySet。
4.可以通过 to_attr 参数指定prefetch到的属性名。
5.Prefetch对象和字符串形式指定的lookups参数可以混用。

4. 最佳实践

1.prefetch_related主要针一对多和多对多关系进行优化。
2.prefetch_related通过分别获取各个表的内容,然后用Python处理他们之间的关系来进行优化。
3.可以通过可变长参数指定需要select_related的字段名。指定方式和特征与select_related是相同的。
4.在Django >= 1.7可以通过Prefetch对象来实现复杂查询,但低版本的Django好像只能自己实现。
5.作为prefetch_related的参数,Prefetch对象和字符串可以混用。
6.prefetch_related的链式调用会将对应的prefetch添加进去,而非替换,似乎没有基于不同版本上区别。
7.可以通过传入None来清空之前的prefetch_related。

选择哪个函数

如果我们想要获得所有家乡是湖北的人,最无脑的做法是先获得湖北省,再获得湖北的所有城市,最后获得故乡是这个城市的人。就像这样:
  1. >>> hb = Province.objects.get(name__iexact=u"湖北省")
  2. >>> people = []
  3. >>> for city in hb.city_set.all():
  4. ... people.extend(city.birth.all())
  5. ...
显然这不是一个明智的选择,因为这样做会导致1+(湖北省城市数)次SQL查询。反正是个反例,导致的查询和获得掉结果就不列出来了。
prefetch_related() 或许是一个好的解决方法,让我们来看看。
  1. >>> hb = Province.objects.prefetch_related("city_set__birth").objects.get(name__iexact=u"湖北省")
  2. >>> people = []
  3. >>> for city in hb.city_set.all():
  4. ... people.extend(city.birth.all())
  5. ...

因为是一个深度为2的prefetch,所以会导致3次SQL查询:

  1. SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name`
  2. FROM `QSOptimize_province`
  3. WHERE `QSOptimize_province`.`name` LIKE '湖北省' ;
  4. SELECT `QSOptimize_city`.`id`, `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`
  5. FROM `QSOptimize_city`
  6. WHERE `QSOptimize_city`.`province_id` IN (1);
  7. SELECT `QSOptimize_person`.`id`, `QSOptimize_person`.`firstname`, `QSOptimize_person`.`lastname`,
  8. `QSOptimize_person`.`hometown_id`, `QSOptimize_person`.`living_id`
  9. FROM `QSOptimize_person`
  10. WHERE `QSOptimize_person`.`hometown_id` IN (1, 3);

嗯…看上去不错,但是3次查询么?倒过来查询可能会更简单?

>>> people = list(Person.objects.select_related("hometown__province").filter(hometown__province__name__iexact=u"湖北省"))
  1. SELECT `QSOptimize_person`.`id`, `QSOptimize_person`.`firstname`, `QSOptimize_person`.`lastname`,
  2. `QSOptimize_person`.`hometown_id`, `QSOptimize_person`.`living_id`, `QSOptimize_city`.`id`,
  3. `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`, `QSOptimize_province`.`id`, `QSOptimize_province`.`name`
  4. FROM `QSOptimize_person`
  5. INNER JOIN `QSOptimize_city` ON (`QSOptimize_person`.`hometown_id` = `QSOptimize_city`.`id`)
  6. INNER JOIN `QSOptimize_province` ON (`QSOptimize_city`.`province_id` = `QSOptimize_province`.`id`)
  7. WHERE `QSOptimize_province`.`name` LIKE '湖北省';
  1. +----+-----------+----------+-------------+-----------+----+--------+-------------+----+--------+
  2. | id | firstname | lastname | hometown_id | living_id | id | name | province_id | id | name |
  3. +----+-----------+----------+-------------+-----------+----+--------+-------------+----+--------+
  4. | 1 | 张 | 三 | 3 | 1 | 3 | 十堰市 | 1 | 1 | 湖北省 |
  5. | 2 | 李 | 四 | 1 | 3 | 1 | 武汉市 | 1 | 1 | 湖北省 |
  6. | 3 | 王 | 麻子 | 3 | 2 | 3 | 十堰市 | 1 | 1 | 湖北省 |
  7. +----+-----------+----------+-------------+-----------+----+--------+-------------+----+--------+
  8. 3 rows in set (0.00 sec)
完全没问题。不仅SQL查询的数量减少了,python程序上也精简了。
select_related()的效率要高于prefetch_related()。因此,最好在能用select_related()的地方尽量使用它,也就是说,对于ForeignKey字段,避免使用prefetch_related()。
对于同一个QuerySet,你可以同时使用这两个函数。在我们一直使用的例子上加一个model:Order (订单)
  1. class Order(models.Model):
  2. customer = models.ForeignKey(Person)
  3. orderinfo = models.CharField(max_length=50)
  4. time = models.DateTimeField(auto_now_add = True)
  5. def __unicode__(self):
  6. return self.orderinfo

如果我们拿到了一个订单的id 我们要知道这个订单的客户去过的省份。因为有ManyToManyField显然必须要用prefetch_related()。如果只用prefetch_related()会怎样呢?

  1. >>> plist = Order.objects.prefetch_related('customer__visitation__province').get(id=1)
  2. >>> for city in plist.customer.visitation.all():
  3. ... print city.province.name
  4. ...

显然,关系到了4个表:Order、Person、City、Province,根据prefetch_related()的特性就得有4次SQL查询

  1. SELECT `QSOptimize_order`.`id`, `QSOptimize_order`.`customer_id`, `QSOptimize_order`.`orderinfo`, `QSOptimize_order`.`time`
  2. FROM `QSOptimize_order`
  3. WHERE `QSOptimize_order`.`id` = 1 ;
  4. SELECT `QSOptimize_person`.`id`, `QSOptimize_person`.`firstname`, `QSOptimize_person`.`lastname`, `QSOptimize_person`.`hometown_id`, `QSOptimize_person`.`living_id`
  5. FROM `QSOptimize_person`
  6. WHERE `QSOptimize_person`.`id` IN (1);
  7. SELECT (`QSOptimize_person_visitation`.`person_id`) AS `_prefetch_related_val`, `QSOptimize_city`.`id`,
  8. `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`
  9. FROM `QSOptimize_city`
  10. INNER JOIN `QSOptimize_person_visitation` ON (`QSOptimize_city`.`id` = `QSOptimize_person_visitation`.`city_id`)
  11. WHERE `QSOptimize_person_visitation`.`person_id` IN (1);
  12. SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name`
  13. FROM `QSOptimize_province`
  14. WHERE `QSOptimize_province`.`id` IN (1, 2);
+----+-------------+---------------+---------------------+
| 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. >>> plist = Order.objects.select_related('customer').prefetch_related('customer__visitation__province').get(id=1)
  2. >>> for city in plist.customer.visitation.all():
  3. ... print city.province.name
  4. ...

这样只会有3次SQL查询,Django会先做select_related,之后prefetch_related的时候会利用之前缓存的数据,从而避免了1次额外的SQL查询:

  1. SELECT `QSOptimize_order`.`id`, `QSOptimize_order`.`customer_id`, `QSOptimize_order`.`orderinfo`,
  2. `QSOptimize_order`.`time`, `QSOptimize_person`.`id`, `QSOptimize_person`.`firstname`,
  3. `QSOptimize_person`.`lastname`, `QSOptimize_person`.`hometown_id`, `QSOptimize_person`.`living_id`
  4. FROM `QSOptimize_order`
  5. INNER JOIN `QSOptimize_person` ON (`QSOptimize_order`.`customer_id` = `QSOptimize_person`.`id`)
  6. WHERE `QSOptimize_order`.`id` = 1 ;
  7. SELECT (`QSOptimize_person_visitation`.`person_id`) AS `_prefetch_related_val`, `QSOptimize_city`.`id`,
  8. `QSOptimize_city`.`name`, `QSOptimize_city`.`province_id`
  9. FROM `QSOptimize_city`
  10. INNER JOIN `QSOptimize_person_visitation` ON (`QSOptimize_city`.`id` = `QSOptimize_person_visitation`.`city_id`)
  11. WHERE `QSOptimize_person_visitation`.`person_id` IN (1);
  12. SELECT `QSOptimize_province`.`id`, `QSOptimize_province`.`name`
  13. FROM `QSOptimize_province`
  14. WHERE `QSOptimize_province`.`id` IN (1, 2);
+----+-------------+---------------+---------------------+----+-----------+----------+-------------+-----------+
| 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将不起作用。

小结

  1. 因为select_related()总是在单次SQL查询中解决问题,而prefetch_related()会对每个相关表进行SQL查询,因此select_related()的效率通常比后者高。
  2. 鉴于第一条,尽可能的用select_related()解决问题。只有在select_related()不能解决问题的时候再去想prefetch_related()。
  3. 你可以在一个QuerySet中同时使用select_related()和prefetch_related(),从而减少SQL查询的次数。
  4. 只有prefetch_related()之前的select_related()是有效的,之后的将会被无视掉。

转载于:https://www.cnblogs.com/wangyue0925/p/11118739.html

Django中的prefetch_related()函数优化相关推荐

  1. Django中prefetch_related()函数优化实战指南

    对于多对多字段(ManyToManyField)和一对多字段, 可以使用prefetch_related()来进行优化 prefetch_related()和select_related()的设计目的 ...

  2. django 中的聚合函数,分组函数,F 查询, Q查询

    先以mysql的语句,聚合用在分组里, 对mysql中groupby 是分组 每什么的时候就要分组,如 每个小组,就按小组分, group by 字段 having 聚合函数 #举例  :求班里的平均 ...

  3. Django 中使用locals()函数的技巧

    对current_datetime 的一次赋值操作: def current_datetime(request):now = datetime.datetime.now()return render( ...

  4. django中聚合aggregate和annotate GROUP BY的使用方法

    接触django已经很长时间了,但是使用QuerySet查询集的方式一直比较低端,只会使用filter/Q函数/exclude等方式来查询,数据量比较小的时候还可以,但是如果数据量很大,而且查询比较复 ...

  5. Django框架(11.Django中的通过模型类查询数据以及相关函数和条件)

     Django中的查询函数 通过模型类.objects属性可以调用如下函数,实现对模型类对应的数据表的查询.    不管哪个函数注意返回值的类型 函数名 功能 返回值 说明 get 返回表中满足条件的 ...

  6. Effective C++条款09:绝不在构造和析构过程中调用virtual函数

    Effective C++条款09:绝不在构造和析构过程中调用virtual函数(Never call virtual functions during construction or destruc ...

  7. Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(二)

    3. prefetch_related() 对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化.或许你会说,没有一个叫OneToMan ...

  8. 实例具体解释Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(二)...

    这是本系列的第二篇,内容是 prefetch_related() 函数的用途.实现途径.以及用法. 本系列的第一篇在这里 第三篇在这里 3. prefetch_related() 对于多对多字段(Ma ...

  9. Django ORM相关操作 select_related和prefetch_related函数对 QuerySet 查询的优化

    在数据库存在外键的其情况下,使用select_related()和prefetch_related()很大程度上减少对数据库的请求次数以提高性能 主要思想就是 '当我们在表中查找一个数据项的时候,我们 ...

最新文章

  1. esp32 linux内核,【小狂系列】跟着小狂玩ESP32之编译环境搭建篇
  2. request.getRequestDispatcher()的两个方法forward()/include()!!!
  3. linux UID,GID,EUID,EGID,SUID,SGID
  4. 新版Microsoft Azure Web管理控制台 - Microsoft Azure New Portal - (3)
  5. php框架所用到的核心概念,【PHP】PHP现代框架代表-Laravel框架核心技术特性
  6. python如何判断是否有弹出框_Selenium2+python自动化47-判断弹出框存在(alert_is_present)【转载】...
  7. submlime text写java_在Sublime Text 3中配置编译和运行Java程序
  8. SpringBoot2.0 基础案例(13):基于Cache注解模式,管理Redis缓存
  9. java8 Optional源码
  10. java图片转字符_java实现图片转字符图(看的过去的亚子)
  11. Pronunciation Difference between /ʌ/ and /ɑ/
  12. 下载dns linux命令,linux dns 部署命令(示例代码)
  13. php spider视频教程,phpspider的简单使用
  14. 旧手机改造成Linux服务器
  15. VR养狗,养的是寂寞还是潮流?
  16. PQ分区魔术师调整硬盘分区大小
  17. Codeforces 731C Socks By Assassin
  18. Raspberry PI 常用命令
  19. 【OpenCV入门教程之五】 分离颜色通道 多通道图像混合
  20. 【cvpr2020】Referring Image Segmentation via Cross-Modal Progressive Comprehension

热门文章

  1. [NOIP2012] 提高组 洛谷P1080 国王游戏
  2. KMP算法 --- 深入理解next数组
  3. Iperf 源代码分析(四)
  4. asp.net 获取访问的url
  5. c语言位运算符怎么用,傻傻分不清
  6. select下拉框如何触发函数并传递参数
  7. mysql 建立一棵树_如何存储一颗树到文件或者数据库
  8. Fiddler跨域调试及Django跨域处理
  9. 有哪些指标可以描述两个图(graph)的相似度?
  10. SushiSwap将于5月17日上线IDO平台Miso