一.持久化数据库连接
django1.6以后已经内置了数据库持久化连接,很多人使用PostgreSQL作为它们的线上数据库系统,而当我们连接PostgreSQL有时会显得很慢,这里我们可以进行优化。
没有持久化连接,每一个网站的请求都会与数据库建立一个连接。如果数据库不在本地,尽管网速很快,这也将花费20-75ms.
设置持久化连接,仅需要添加CONN_MAX_AGE参数到你的数据库设置中:
DATABASES = {
‘default’: {
‘ENGINE’: ‘django.db.backends.postgresql_psycopg2’,
‘NAME’: ‘whoohoodb’,
‘CONN_MAX_AGE’: 600,
}
}
通过这样的设置,我们设置的持久化连接每次都将存活10分钟
这有助于减少内存泄漏或导致一种片状连接的问题。
你可设置更长的时间,但是我不要设置超过1个小时,因为这样获得的效果不会太好。
二.一次性取出你所需要的数据
单一动作(如:同一个页面)需要多次连接数据库时,最好一次性取出所有需要的数据,减少连接数据库次数。
此类需求推荐使用QuerySet.select_related() (主动连表)和 prefetch_related()(被动连表),在使用ORM的情况下,他能够减少sql查询的数量。
相反,别取出你不需要的东西,模板templateds里往往只需要实体的某几个字段而不是全部,这时使用queryset.values()和values_list()对你有用,他们只取出你需要的字段,返回字典dict和列表list类型的东西,在模板里面够用就可以,这可以减少内存损耗,提高性能。
使用queryset.count()代替len(queryset),虽然这两个处理出来的结果是一样的,但是前者性能优秀很多。同理判断记录存在的时候,queryset.exists()比if queryset实在强的太多了。
三.利用好Django的QuerySets
QuerySets是有缓存的,一旦取出来,它就会在内存里呆上一段时间,尽量重用它。
# 了解缓存属性:
entry = Entry.objects.get(id=1)
entry.blog # 博客实体第一次取出,是要访问数据库的
entry.blog # 第二次再用,那它就是缓存里的实体了,不再访问数据库
entry = Entry.objects.get(id=1)
entry.authors.all() # 第一次all函数会查询数据库
entry.authors.all() # 第二次all函数还会查询数据库
all,count exists是调用函数(需要连接数据库处理结果的),注意在模板template里的代码,模板里不允许括号,但如果使用此类的调用函数,一样去连接数据库的,能用缓存的数据就别连接到数据库去处理结果。还要注意的是,自定义的实体属性,如果调用函数的,记得自己加上缓存策略。当缓存里面已经存在的时候,就别再滥用count(),exitst(),all()函数了。
利用好模板的with标签:
模板中多次使用的变量,要用with标签,把它看成变量的缓存行为吧。
使用QuerySets的iterator():
通常QuerySets先调用iterator再缓存起来,当获取大量的实体列表而仅使用一次时,缓存行为会耗费宝贵的内存,这时iterator()能帮到你,iterator()只调用iterator而省 去了缓存步骤,显著减少内存占用率。
四.利用标准数据库优化技术
传统数据库优化技术博大精深,不同的数据库有不同的优化技巧,但重心还是有规则的。在这里算是题外话,挑两点通用的说说:
索引,给关键的字段添加索引,性能能更上一层楼,如给表的关联字段,搜索频率高的字段加上索引等。Django建立实体的时候,支持给字段添加索引,具体参考Django.db.models.Field.db_index。按照经验,Django建立实体之前应该早想好表的结构,尽量想到后面的扩展性,避免后面的表的结构变得面目全非。
使用适当字段类型,本来varchar就搞定的字段,就别要text类型,小细节别不关紧要,后头数据量一上去,愈来愈多的数据,小字段很可能是大问题。
五.减少数据库连接的次数
使用queryset.update()和delete(),这两个函数是可以批量处理多条记录的,使他们事半功倍;如果可以,被一条条数据去update delete处理,对于一次性取出来的关联记录,获取外键的时候,直接取关联表的属性,而不是取关联属性。
entry.blog.id
优于
entry.blog__id
# 善于使用批量插入记录,如:
Entry.objects.bulk_create([
Entry(headline="Python 3.0 Released"),
Entry(headline="Python 3.1 Planned")
])
优于
Entry.objects.create(headline="Python 3.0 Released")
Entry.objects.create(headline="Python 3.1 Planned")
# 前者只连接一次数据库,而后者连接两次
# 还有相似的动作需要注意的,如:多对多的关系,
my_band.members.add(me, my_friend)
优于
my_band.members.add(me)
my_band.members.add(my_friend)
六.在配置使用相对路径
某些原因使得项目可能常常会被来回的迁移,如果事先没有规划好这种可能性的话,这绝对是一个棘手的问题,有一个极好的技巧能够确保你的Django项目在部署的过程中能够轻松来回迁移,仅仅只需要编写几行代码就可以在你的配置文件settings.py中。
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')],
},
]
# xadmin应用
sys.path.insert(0, os.path.join(BASE_DIR, 'extra_apps'))
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
# pd statics
# STATIC_ROOT = os.path.join(BASE_DIR,"allstatic")
#上传文件图片的根路径
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
#访问文件的URL
MEDIA_URL = '/media/'
# Ansible 资源池配置文件
INVENT_PATH = os.path.join(BASE_DIR, 'octopus/inventory/hosts')
七.使用缓存
如果性能在你的DJango项目中已经成为棘手的问题,那么你将需要使用一些缓存策略,然而Django为缓存提供很多的选择,目前最好的无疑是Memcache,用Django安装memcache非常的简单,如果你使用memcache模块的时候,只要模块安装完成后,你仅仅修改一行配置项,你的Django页面变得轻快起来。
八.在代码方面的优化
核心模块使用cpython来实现,大幅度提高代码的运行速度。
九.使用Django-debug-toolbar调试优化
它是一个非常方便的工具,可以深入了解代码的工作以及它花费了多少时间。特别是他可以显示你的页面生成的SQL查询,以及每个人花了多少时间。
十.缓存集群
1、模板加载
默认django使用两个标准的模版加载器
TEMPLATE_LOADERS = (
‘django.template.loaders.filesystem.Loader’,
‘django.template.loaders.app_directories.Loader’,
)
每一个请求,这些模版加载器都会去文件系统搜索,然后解析这些模版。
这里可以感觉到,它是不是可以处理的更快了?
你可以开启缓存加载,因此django只会查找并且解析你的模版一次
配置如下:
TEMPLATE_LOADERS = (
(‘django.template.loaders.cached.Loader’, (
‘django.template.loaders.filesystem.Loader’,
‘django.template.loaders.app_directories.Loader’,
)),
)
但是,不要在开发环境中开启缓存加载,这样会很烦人的,因为每次模版做了修改之后你都需要重启服务才能看到修改后的效果。
2、前后端分离
我们使用drf框架,前后端分离,直接从api接口获取数据使用vue将后端获得的json数据渲染到前端,并且拥有查询以及分页功能,数据是一次性取出,减少访问数据库的次数。
3、页面静态化
对于主页,信息丰富,需要多次查询数据库才能得到全部数据。
如果用户每次访问主页,都做多次数据库查询,性能差。
优化:将主页存储成静态页面,用户访问时,响应静态页面
实现:把render()返回的html数据存储起来
以上是wed服务器优化方案之一,把页面静态化,减少服务器处理动态数据的压力
4、配置nginx
nginx服务器可以实现负载均衡以及反向代理。
使用nginx访问静态页面,nginx服务器提供静态数据效率高。
5、celery 执行异步任务
使用celery实现任务队列即异步进行,使用redis以及rabbitmq做为中间人。
redis可以做缓存服务器。
网友评论