bigywater.tech
Django · 101

Django Debug Toolbar 分析慢查询

Debug Toolbar 是发现 N+1 和重复查询最快的办法:把它装在开发环境,页面右边的 SQL 面板会列出每条查询、耗时、调用栈,并标出相似与重复的查询。这篇用 django.test.Client 请求一个真实带工具栏的页面,取出 SQL 面板的内容,再量一下它自己的开销。

101 → 1
N+1 页面的查询数:未优化 → select_related
100 similar
面板把同一模板的查询归为 similar,参数也相同的归为 duplicate
10.31 → 22.24 ms
同一页面有工具栏后的请求耗时(30 次中位数)

工具栏的数据怎么来的

实测 · 本机执行输出
响应状态 200  响应里有工具栏(djDebug)吗: True
request_id 形如: b7d73367… (每个请求一个,面板内容存在服务端,前端按它取)
SQL 面板摘要: default 1.77 ms (101 queries including 100 similar and 100 duplicates )
提示行: ['100 similar queries. Duplicated 10 times.', '100 similar queries. Duplicated 10 times.']
面板里带调用栈(能看到是哪一行代码发的查询)——出现 views.py 行: True  出现 site-packages 行: True

工具栏中间件在响应里注入一段脚本和 data-request-id,面板本身的内容存在服务端,浏览器按 request_id 再发请求(这里请求 /__debug__/render_panel/ 取 SQL 面板)。实验里设置了 INTERNAL_IPS = ["127.0.0.1"] 和 DEBUG = True;不满足这两个条件时的表现本文没有测。

修复之后

实测 · 本机执行输出
修复后 SQL 面板摘要: default 0.05 ms (1 query )

同样的页面用 select_related 后只有一次查询。

重复查询

实测 · 本机执行输出
SQL 面板摘要: default 0.10 ms (3 queries including 3 similar and 3 duplicates )
提示: ['3 similar queries. Duplicated 3 times.', '3 similar queries. Duplicated 3 times.', '3 similar queries. Duplicated 3 times.']

N+1 是「相似」的一类;还有一类是完全相同的查询被重复执行。面板都会标出来,并给出 Duplicated 的次数。

工具栏自己的开销

实测 · 本机执行输出
  没有工具栏    10.31 ms
  有工具栏     22.24 ms

它要记录每条查询、抓调用栈,所以请求会明显变慢。对比耗时应当在关掉工具栏的情况下量,不要拿带工具栏的数字当性能结论。

分步演示:从面板读出问题

Debug Toolbar 的 SQL 面板
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7 / Django 6.1.1(默认用 SQLite,其它数据库会在文中注明),用 django.test.Client 或真实的本机服务器进程实测;计时用 time.perf_counter,数字每次运行会有小幅抖动。SQLite;django-debug-toolbar 由 pip 装入(版本以 pip 安装时的最新版为准);面板内容由 django.test.Client 直接请求 render_panel 端点取得并去掉 HTML 标签
    • 没有验证:浏览器里工具栏的实际界面、EXPLAIN 按钮、Profiling 面板、生产环境远程调试、其它数据库上的 EXPLAIN 输出、异步视图下的工具栏行为
    京ICP备2026067502号-1京公网安备11010502063487号