如何在 django 应用程序中自动识别 n+1 个查询?

375 阅读1分钟

之前我们有介绍过使用django-auto-prefetching来解决Django REST 框架和 n+1 问题。是否有任何工具、插件和技术可用于帮助我们识别 Django 应用程序上的 n+1 个查询?今天我们将介绍二种方式,其中django-debug-toolbar或许大家都很熟悉。

django-debug-toolbar

Django 的调试工具栏。可显示当前请求和响应有关的各种调试信息,包括耗时、SQL、配置、性能等信息。

d8bc099bf1d81429c6d863a53dd9b51.png

nplusone

nplusone是一个 ORM 分析工具,用于帮助诊断和改进由不适当的延迟加载导致的性能不佳。nplusone使用 Django 或 SQLAlchemy 监视应用程序,并在可能产生昂贵的惰性加载时发送通知。它可以识别问题背后的违规关系属性和特定代码行,并为更好的性能提出修复建议。

安装

pip install -U nplusone

注意

  • 1、nplusone 支持 Python >= 2.7 或 >= 3.3。
  • 2、nplusone只能用于开发,不能部署到生产环境。
  • 3、nplusone支持 Django >= 1.8。

Django用法

添加nplusone到INSTALLED_APPS:

INSTALLED_APPS = ( 
    ... 
    'nplusone.ext.django', 
)

添加中间件NPlusOneMiddleware:

MIDDLEWARE = (
    'nplusone.ext.django.NPlusOneMiddleware',
    ...
)

可选配置日志记录设置:

NPLUSONE_LOGGER = logging.getLogger('nplusone')
NPLUSONE_LOG_LEVEL = logging.WARN

配置日志处理程序:

LOGGING = {
    'version'1,
    'handlers': {
        'console': {
            'class''logging.StreamHandler',
        },
    },
    'loggers': {
        'nplusone': {
            'handlers': ['console'],
            'level''WARN',
        },
    },
}

日志

当您的应用程序延迟加载数据时,nplusone将发出日志消息:

Potential n+1 query detected on `<model>.<field>`
orders = OutboundOrder.objects.all()  
for order in orders:
    owner_name = order.owner.name   #未使用.select_related('owner')或者prefetch_related

d7605d051cdb69df28a92167f21868c.png

在这种情况下,请考虑使用select_relatedprefetch_related

当您的应用急切加载相关数据而不访问它时,nplusone将记录警告:

Potential unnecessary eager load detected on `<model>.<field>`
orders = OutboundOrder.objects.all().select_related('owner')
for order in orders:
    print(order)  # 使用了.select_related('owner') 未对owner数据进行访问

14f1110f749631eebf232a67c953156.png

扫码_搜索联合传播样式-标准色版.png