初窥django性能优化

理解我们为什么优化?优化的瓶颈在哪,在条件清楚后我们才好对症下药。

django-optimize

一:性能度量分析

django-silk地址:
GitHub - jazzband/django-silk: Silky smooth profiling for Django

https://docs.djangoproject.com/zh-hans/2.1/topics/performance/

二:优化方式

1.缓存机制(可以将下静态数据或更新频率较小的做缓存)

内存缓存:memcached
数据库缓存: redis(django-redis)
文件系统缓存:file

点击并拖拽以移动

2.ORM

1. persistment database connections(持久化连接)
2.Django中的惰性会延迟计算,只有真正需要的时候才会去计算,避免过早地对 QuerySet 进行计算,可以节省对数据库进行一次昂贵而不必要的访问
3. queryset会在缓存,尽量重用
4. use the with template tag,use iterator(),use explain()
5. Do database work in the database rather than in python 
   用blogs.objects.exclude blog.objects.filter查询过滤
   queryset.count 代替len(queryset)
   queryset.exists 代替if queryset
5. 只取需要的数据
   blog.objects.values()    返回字典列表
   blog.objects.values_list() 返回元组列表
   blog.objects.defer('name') 排除不需要的字段
   blog.objects.only('name') 仅取需要的字段
6. 关联查询blog.objects.select_related.get() 尽量深入查询关联的数据(大量外键时
   entry.blog_name代替entry.blog.name 
   select_related: 仅限于单值关系 - 外键(多对一)和一对一
   prefetch_related: 预取 多对多和多对一对象

8.使用queryset.update和queryset.delete来批量处理

点击并拖拽以移动

select_related:对于一对一字段(OneToOneField)和**多对一字段(ForeignKey),**可以使用select_related 来对QuerySet进行优化。select_related使获取相应外键对应的对象,不必再查询数据库了。原理:select_related使用SQL的JOIN语句进行优化,通过减少SQL查询的次数来进行优化、提高性能。

# 深度
queryset = Person.objects.select_related(depth=3)
# 外键的外键的字段名
queryset = Person.objects.select_related("hometown__province","living__province").all()
# 链式
queryset = Person.objects.select_related("hometown__province").select_relate("living_province").all()
for item in queryset:
    print(item.hometown.province)
    print(item.living.province)

点击并拖拽以移动

prefetch_related: 2.对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化。原理:不用sql语句解决,分别查询每个表,用python处理之间的关系。注意:可以在调用prefetch_related之前调用select_related。先select_related,然后利用缓存到的数据prefetch_related。然而prefetch_related已经调用,select_related将不起作用。

queryset = Person.objects.prefetch_related("visitation__province").all()

for item in queryset:
    for city in item.visitation.all():
         print(city.province)

# QuerySet链式操作改变了数据库请求,之前用的prefetch_related缓存将被忽略,会重新请求数据库.
# 如:
    for city in item.visitation.filter(name__icontains=""):
         print(city.province)

点击并拖拽以移动

3.数据库读写分离

采用数据读写分离,降低数据库压力

4.celery

对不需要立即返回的,可以借助于celery做异步任务

5.部署方案

使用高性能的部署策略

nginx+uWSGI+django
nginx+gunicorn+django 
nginx+apache+mod_wsgi+django

点击并拖拽以移动


初窥django性能优化
https://centyuan.github.io/2023/11/06/Python从入门到放弃/初窥django性能优化/
作者
hlyuan
发布于
2023年11月6日
许可协议