大道至简,知行合一。

Django ORM性能优化

Django是个好工具,使用的很广泛。 在应用比较小的时候,会觉得它很快,但是随着应用复杂和壮大,就显得没那么高效了。当你了解所用的Web框架一些内部机制之后,才能写成比较高效的代码。

查询问题的思路

Web系统是个挺复杂的玩意,有时候有点无从下手哈。可以采用 自底向上 的顺序,从数据存储一直到数据展现,按照这个顺序一点一点查找性能问题。

  1. 数据库 (缺少索引/数据模型)
  2. 数据存储接口 (ORM/低效的查询)
  3. 展现/数据使用 (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语句查询的时间,当然就知道那里慢了)

>>> 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 选项。

python manage.py shell_plus --print-sql
>>> 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请求进行捕获处理。

sudo pip install django-debug-toolbar
sudo pip install git+https://github.com/djsutho/django-debug-toolbar-request-history.git

配置

1.修改settings.py

INSTALLED_APPS = (
    ...
    'debug_toolbar',
    ...
)

MIDDLEWARE_CLASSES = (
    ...
    'debug_toolbar_middleware.DebugToolbarMiddleware',
    ...
)

INTERNAL_IPS = ['127.0.0.1']    # 从哪些站点访问会显示debug-toolbar

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

from django.conf import settings

if settings.DEBUG:
    import debug_toolbar
    urlpatterns += [
        path(r'__debug__/', include(debug_toolbar.urls)),
    ]

使用效果

总结

预加载是 Django REST Framework 通用的性能优化方式,OneAPM Python Agent 也是国内通用的性能监控工具,而且支持 Django REST Framework ,下面是一个简单 demo 的截图。任何时候你通过 ORM 查询嵌套关系时,你都应该考虑建立适合的预加载。根据现有经验,这是现在小型和中型 Web 开发中最常见的性能相关问题。

参考文献

赞(0)
未经允许不得转载:北凉柿子 » Django ORM性能优化
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址