请选择 进入手机版 | 继续访问电脑版

[数据库其它] Django项目优化数据库操作总结

[复制链接]
查看122 | 回复34 | 2021-9-12 07:11:46 | 显示全部楼层 |阅读模式
目次

参考网址:Django官方数据库优化

利用 QuerySet.explain() 来相识 你的数据库是怎样 实行 特定的 QuerySet 的。

你大概 还想利用 一个外部项目,比如 django-debug-toolbar ,或者一个直接监控数据库的工具。

合理的创建索引

索引大概 有助于加快查询速率 ,但是也要留意 索引会占用磁盘空间,创建不必要的索引只会形成浪费。数据库表中的主键、外键、唯一键默认会创建索引。
那么哪些字段必要 创建索引呢?这是一个好的且令人疑惑 的标题 ,下面列出的几条可以作为参照意见:

  • 频仍 出如今 WHERE条件子句的字段(也就是Django里filter筛选的字段)
  • 常常 被用来分组(group by)或者排序(order by)的字段
  • 在常常 存取的多个列上创建复合索引,但要留意 复合索引的次序 要按照利用 的频度来决定
  1. class ModelName(models.Model):
  2. # 字段添加索引使用db_index
  3. name = models.CharField(db_index=True, max_length=100)
  4. class Meta:
  5. # 联合唯一索引使用index_together
  6. index_together = ('字段1', '字段2')
复制代码

设置数据库持久毗连

减少SQL的实行 次数

多次访问数据库比单次查询全部 内容的服从 低。因此明白 并学会利用 select_related() 和 prefetch_related() 。

select_related():创建一个 SQL 毗连 ,并在 SELECT 语句中包含相干 对象的字段。一样寻常 用于一对多(ForeignKey)和一对一(OneToOneField)关系

  1. # 标准查询
  2. # Hits the database.
  3. e = Entry.objects.get(id=5)
  4. # Hits the database again to get the related Blog object.
  5. b = e.blog
  6. # select_related 查询
  7. # Hits the database.
  8. e = Entry.objects.select_related('blog').get(id=5)
  9. # Doesn't hit the database, because e.blog has been prepopulated
  10. # in the previous query.
  11. b = e.blog
复制代码

prefetch_related(): 一样寻常 用于多对一(GenericForeignKey)和多对多(ManyToManyField)关系

  1. from django.db import models
  2. class Topping(models.Model):
  3. name = models.CharField(max_length=30)
  4. class Pizza(models.Model):
  5. name = models.CharField(max_length=50)
  6. toppings = models.ManyToManyField(Topping)
  7. def __str__(self):
  8. return "%s (%s)" % (
  9. self.name,
  10. ", ".join(topping.name for topping in self.toppings.all()),
  11. )
  12. # Good
  13. pizza.objects.all().prefetch_related('toppings')
复制代码

仅获取必要 的字段数据

利用 QuerySet.values() 和 values_list()

利用 QuerySet.defer() 和 only()

利用 QuerySet.count()

利用 QuerySet.exists()

请不要过度利用 count() 和 exists()

利用 批量创建、更新和删除,不随意对结果 排序

批量创建: 当创建对象时,尽大概 利用 bulk_create() 方法来减少 SQL 查询数量 。比如:

  1. # Good
  2. Entry.objects.bulk_create([
  3. Entry(headline='This is a test'),
  4. Entry(headline='This is only a test'),
  5. ])
  6. # Bad
  7. Entry.objects.create(headline='This is a test')
  8. Entry.objects.create(headline='This is only a test')
复制代码

批量更新: 当更新对象时,尽大概 利用 bulk_update() 方法来减少 SQL 查询数。给定对象的列表或查询集:

  1. # Good
  2. entries[0].headline = 'This is not a test'
  3. entries[1].headline = 'This is no longer a test'
  4. Entry.objects.bulk_update(entries, ['headline'])
  5. # Bad
  6. entries[0].headline = 'This is not a test'
  7. entries[0].save()
  8. entries[1].headline = 'This is no longer a test'
  9. entries[1].save()
复制代码

批量插入: 当插入对象到 ManyToManyFields 时,利用 带有多个对象的 add() 来减少 SQL 查询的数量 。

举例:

  1. # Good
  2. my_band.members.add(me, my_friend)
  3. # Bad
  4. my_band.members.add(me)
  5. my_band.members.add(my_friend)
  6. # Good
  7. PizzaToppingRelationship = Pizza.toppings.through
  8. PizzaToppingRelationship.objects.bulk_create([
  9. PizzaToppingRelationship(pizza=my_pizza, topping=pepperoni),
  10. PizzaToppingRelationship(pizza=your_pizza, topping=pepperoni),
  11. PizzaToppingRelationship(pizza=your_pizza, topping=mushroom),
  12. ], ignore_conflicts=True)
  13. # Bad
  14. my_pizza.toppings.add(pepperoni)
  15. your_pizza.toppings.add(pepperoni, mushroom)
复制代码

批量删除: 当从 ManyToManyFields 删除对象时,可以利用 带有多个对象的 remove() 来减少 SQL 查询的数量 。

比如:

  1. # Good
  2. my_band.members.remove(me, my_friend)
  3. # Bad
  4. my_band.members.remove(me)
  5. my_band.members.remove(my_friend)
  6. # Good
  7. from django.db.models import Q
  8. PizzaToppingRelationship = Pizza.toppings.through
  9. PizzaToppingRelationship.objects.filter(
  10. Q(pizza=my_pizza, topping=pepperoni) |
  11. Q(pizza=your_pizza, topping=pepperoni) |
  12. Q(pizza=your_pizza, topping=mushroom)
  13. ).delete()
  14. # Bad
  15. my_pizza.toppings.remove(pepperoni)
  16. your_pizza.toppings.remove(pepperoni, mushroom)
复制代码

以上就是Django项目优化数据库操作总结的详细 内容,更多关于Django项目优化数据库的资料请关注脚本之家别的 相干 文章!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

avatar Harry192 | 2021-9-12 17:50:52 | 显示全部楼层
十分赞同admin楼主!
回复

使用道具 举报

avatar Deville | 2021-9-15 22:18:05 | 显示全部楼层
不是惊喜,是惊吓!
回复

使用道具 举报

avatar ggp27 | 2021-9-18 04:10:43 | 显示全部楼层
刚看见一个妹子,很漂亮!
回复

使用道具 举报

avatar 落木萧萧329 | 2021-9-18 12:27:12 | 显示全部楼层
很经典,收藏了!
回复

使用道具 举报

avatar 旭日非常 | 2021-9-20 16:51:27 | 显示全部楼层
突然觉得admin楼主说的很有道理,赞一个!
回复

使用道具 举报

avatar 极品小处男处v | 2021-10-4 09:40:34 | 显示全部楼层
admin楼主你想太多了!
回复

使用道具 举报

avatar 十年2017 | 2021-10-5 12:45:05 | 显示全部楼层
被admin楼主的逻辑打败了!
回复

使用道具 举报

avatar Gemini迷妹 | 2021-10-5 12:45:08 | 显示全部楼层
收藏了,很不错的内容!
回复

使用道具 举报

avatar 击管虽您 | 2021-10-7 01:37:06 | 显示全部楼层
祖国尚未统一,我却天天灌水,好内疚!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则