You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django Shell中计时查询的最佳方式是什么?如何优化查询性能?

在Django Shell中优化查询性能的进阶方法

嘿,你在shell_plus里用%timeit对比查询速度的思路已经很靠谱了!不过确实还有几个更灵活、更深入的方法,能帮你全方位分析Django查询的性能,我来分享几个日常开发里常用的技巧:

1. 用Django自带的connection.queries追踪SQL与耗时

这个方法能让你看到Django实际生成并执行的SQL语句,以及每个查询的精确耗时,非常适合对比不同查询写法的底层差异。

举个简单的例子:

from django.db import connection

# 先清空之前的查询记录,避免干扰
connection.queries.clear()

# 执行你要测试的查询
qs = MyModel.objects.filter(category="books").select_related("author")
results = list(qs)

# 查看最后一次查询的耗时和SQL
last_query = connection.queries[-1]
print(f"查询耗时: {last_query['time']} 秒")
print(f"执行的SQL:\n{last_query['sql']}")

小贴士:每次测试前记得调用connection.queries.clear(),这样你看到的就是当前查询的真实数据。

2. 结合time模块手动精准计时

如果你不想依赖IPython的%timeit,可以用Python标准库的time.perf_counter()来手动控制计时范围,比如你想测从查询到数据处理完成的完整耗时:

import time

start = time.perf_counter()

# 执行查询+数据处理
queryset = MyModel.objects.all().prefetch_related("tags")
processed_data = [item.name for item in queryset]

end = time.perf_counter()

print(f"完整流程耗时: {end - start:.4f} 秒")

这种方法的好处是灵活性高,你可以自由包裹需要计时的代码段。

3. 用explain()查看数据库执行计划

单纯计时只能知道“快/慢”,而explain()能告诉你“为什么快/慢”。Django 2.1+支持这个方法,它会返回数据库的执行计划,帮你判断查询有没有用到索引、是否做了全表扫描等关键信息。

用法很简单:

# 查看基础执行计划
MyModel.objects.filter(author_id=123).explain()

# 查看详细执行计划(支持PostgreSQL、MySQL等主流数据库)
MyModel.objects.filter(author_id=123).explain(verbose=True)

通过执行计划,你能快速定位到查询的性能瓶颈,比如发现某个过滤条件没用到索引,就可以针对性地添加索引优化。

4. 写个小工具批量对比多个查询

如果要同时测试好几种查询写法,手动重复计时太麻烦,你可以写个简单的基准测试函数,自动帮你跑多次测试并计算平均值:

import time
from django.db import connection

def benchmark(query_func, runs=5):
    total_time = 0.0
    print(f"开始测试,共执行{runs}次...")
    
    for i in range(runs):
        connection.queries.clear()
        start = time.perf_counter()
        # 执行查询函数
        query_func()
        end = time.perf_counter()
        
        run_time = end - start
        total_time += run_time
        print(f"第{i+1}次耗时: {run_time:.4f} 秒")
        # 可选:打印本次执行的SQL
        # print(f"SQL: {connection.queries[-1]['sql']}")
    
    avg_time = total_time / runs
    print(f"\n平均耗时: {avg_time:.4f} 秒")
    return avg_time

# 定义你要测试的查询函数
def query_without_related():
    return list(MyModel.objects.filter(category="books"))

def query_with_select_related():
    return list(MyModel.objects.filter(category="books").select_related("author"))

# 运行对比
print("=== 测试无关联查询 ===")
benchmark(query_without_related)
print("\n=== 测试带select_related的查询 ===")
benchmark(query_with_select_related)

最后补充

其实%timeit依然是非常好用的工具——它会自动帮你多次运行取平均值,减少单次执行的误差,适合快速对比简单查询的速度。上面这些方法更多是作为补充,帮你在计时之外,深入理解查询的底层逻辑和性能瓶颈。

内容的提问来源于stack exchange,提问作者Myroslav Hryshyn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:16:08