Django是个好工具,使用的很广泛。 在应用比较小的时候,会觉得它很快,但是随着应用复杂和壮大,就显得没那么高效了。当你了解所用的Web框架一些内部机制之后,才能写成比较高效的代码。
查询问题的思路
Web系统是个挺复杂的玩意,有时候有点无从下手哈。可以采用 自底向上
的顺序,从数据存储一直到数据展现,按照这个顺序一点一点查找性能问题。
- 数据库 (缺少索引/数据模型)
- 数据存储接口 (ORM/低效的查询)
- 展现/数据使用 (Views/报表等)
Web应用的大部分问题都会跟数据库扯上关系。除非你正在处理大量的数据并知道你在做什么,否则不要去考虑用Big-O表示法思考View的问题。 数据库调用的开销将使循环和模板渲染的开销相形见绌。 不首先解决数据库使用中的问题,您就不能继续解决其他问题。
Django的文档中有那么一节,详细的描述了 DB部分优化, ORM 从一开始就应该写的比较高效一些(毕竟有那么多最佳实践)
优化,很多时候意味着代码可能变得不太清晰。当你遇到选择清晰的代码,还是牺牲清晰代码来获取性能上的一点点提高的时候,请优先考虑要代码的清晰整洁。
辅助优化的工具
解决问题的第一步是找到问题,针对ORM优化,主要有以下工具:
django.db.connection
: django自身提供,比较底层;- django-extensions: 可以在shell环境下方面调试;
- django-debug-toolbar:可以在web端直接看到debug结果;
django.db.connection
理解 django.db.connection
, 这个对象可以用来记录当前查询花费的时间(知道了SQL语句查询的时间,当然就知道那里慢了)
1 2 3 4 5 6 7 |
>>> from django.db import connection >>> connection.queries [] >>> Author.objects.all() <QuerySet [<Author: Author object>]> >>> connection.queries [{u'time': u'0.002', u'sql': u'SELECT "library_author"."id", "library_author"."name" FROM "library_author" LIMIT 21'}] |
但是使用起来好像不是很方面。
django-extensions
在shell命令行的环境下,可以使用 django-exension’s shell_plus
命令并打开 --print-sql
选项。
1 |
python manage.py shell_plus --print-sql |
1 2 3 4 |
>>> Author.objects.all() SELECT "library_author"."id", "library_author"."name" FROM "library_author" LIMIT 21 Execution time: 0.001393s [Database: default] <QuerySet [<Author: Author object>]> |
Django-debug-toolbar
还有个更方便的方式, 使用 Django-debug-toolbar 工具,就可以在web端查看SQL查询的详细统计结果,其实它功能远不止这个。
调试与优化时,我们常常想知道比如以下问题:
- 执行了多少条 SQL 语句,花费的时间,每次每条语句查询的时间
- 渲染页面的模板是哪些,渲染时间
- 缓存是否影响性能
总结来看,django-debug-toolbar 是一款非常强大的 Django 的性能检测工具,是Django ORM 性能优化推荐使用的工具,下面我们着重介绍以下它。
Django-debug-toolbar 使用
安装
这里安装的插件还针对ajax请求进行捕获处理。
1 2 |
sudo pip install django-debug-toolbar sudo pip install git+https://github.com/djsutho/django-debug-toolbar-request-history.git |
配置
1.修改settings.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
INSTALLED_APPS = ( ... 'debug_toolbar', ... ) MIDDLEWARE_CLASSES = ( ... 'debug_toolbar_middleware.DebugToolbarMiddleware', ... ) INTERNAL_IPS = ['127.0.0.1'] # <em>从哪些站点访问会显示debug-toolbar</em> DEBUG_TOOLBAR_PANELS = [ 'ddt_request_history.panels.request_history.RequestHistoryPanel', 'debug_toolbar.panels.versions.VersionsPanel', 'debug_toolbar.panels.timer.TimerPanel', 'debug_toolbar.panels.settings.SettingsPanel', 'debug_toolbar.panels.headers.HeadersPanel', 'debug_toolbar.panels.request.RequestPanel', 'debug_toolbar.panels.sql.SQLPanel', 'debug_toolbar.panels.staticfiles.StaticFilesPanel', 'debug_toolbar.panels.templates.TemplatesPanel', 'debug_toolbar.panels.cache.CachePanel', 'debug_toolbar.panels.signals.SignalsPanel', 'debug_toolbar.panels.logging.LoggingPanel', 'debug_toolbar.panels.redirects.RedirectsPanel', ] DEBUG_TOOLBAR_CONFIG = { 'SHOW_TOOLBAR_CALLBACK': 'ddt_request_history.panels.request_history.allow_ajax', } |
2. 修改urls.py
1 2 3 4 5 6 7 |
<strong>from </strong>django.conf <strong>import </strong>settings <strong>if </strong>settings.DEBUG: <strong>import </strong>debug_toolbar urlpatterns += [ path(<strong>r'__debug__/'</strong>, include(debug_toolbar.urls)), ] |
使用效果
总结
预加载是 Django REST Framework 通用的性能优化方式,OneAPM Python Agent 也是国内通用的性能监控工具,而且支持 Django REST Framework ,下面是一个简单 demo 的截图。任何时候你通过 ORM 查询嵌套关系时,你都应该考虑建立适合的预加载。根据现有经验,这是现在小型和中型 Web 开发中最常见的性能相关问题。

参考文献
- Django ORM性能优化,数据存取优化
- 优化Django ORM中的性能问题(含prefetch_related 和 select_related)
- django-debug-toolbar: django开发之性能强大的检测工具
转载请注明:北凉柿子 » Django ORM性能优化