Django ORM查询较原生SQL慢数倍,该现象是否正常?
Django ORM 查询比原生SQL慢数倍,这正常吗?
问题背景
你遇到的情况是:用matches.query.__format__('')拿到Django查询对应的原生SQL后,在psql里直接执行只需要5-10ms,但在Django视图中首次执行这个查询集却要花费100ms左右,这种性能差异让你担心会影响用户体验。你的视图代码如下:
import time from django.http import JsonResponse from .models import Relationship def api(request): tag = request.GET.get('q', '') matches = Relationship.objects.filter(keyword=tag, count__gte=3).order_by('-count')[:30] print(matches.query.__format__('')) # 获取原生SQL start_time = time.time() print(matches) # 惰性查询在此执行 print("Time elapsed {0:0.1f}ms".format((time.time() - start_time) * 1000)) mydict = serialize_matches(matches, tag) return JsonResponse(mydict)
原因分析(结合你的更新)
一开始看到这种差异,很容易怀疑是Django ORM的额外开销,但从你后续的排查结果来看,问题出在数据库缓存的测试偏差上:
- 当你在
psql中重复执行同一查询时,PostgreSQL的shared_buffers(数据库级缓存)或者操作系统的文件系统缓存已经把查询需要的数据加载到内存里了,所以后续执行速度极快。 - 哪怕你重启了
psql客户端,数据库服务本身的缓存和OS级缓存依然存在,这会让你误以为原生SQL的“真实执行速度”就是5-10ms,但实际上这是缓存命中后的速度。 - 而Django首次执行查询时,可能刚好是数据库缓存未命中的情况(比如服务器重启后、或者该数据很久没被访问过),这时需要从磁盘读取数据,所以耗时会明显更长——这才是查询的真实冷启动耗时,和Django ORM本身关系不大。
额外验证建议(可选)
如果想确认Django ORM的真实开销,可以做以下测试:
- 在Django中连续执行两次相同查询,第二次的耗时应该会和
psql的缓存后耗时接近,因为第一次已经把数据加载到缓存里了。 - 使用PostgreSQL的
EXPLAIN ANALYZE命令在psql中执行冷查询(比如先重启数据库服务后执行),这时得到的耗时应该和Django首次执行的耗时更接近。
结论
从你的更新来看,Django本身并没有问题,性能差异的核心是测试时的缓存状态不一致导致的误解。只要确保数据库的缓存策略合理,后续用户重复查询时的性能会和你在psql中看到的缓存后速度一致。
内容的提问来源于stack exchange,提问作者M3RS
相关产品推荐
相关产品推荐

