Django ORM查询耗时久但Raw Query速度正常的原因排查
针对你遇到的ORM查询耗时是Raw SQL近100倍的问题,结合表数据量极小(仅20条)的情况,核心原因大概率出在ORM的额外逻辑上,以下是具体排查方向:
模型关联与字段加载冗余
ORM的get()方法默认会加载模型的所有字段,若TenantKey定义了外键、ManyToMany等关联关系,即使你没用到这些关联数据,Django可能会触发懒加载(首次访问关联字段时)或因配置不当触发预加载,产生额外查询。而你的Raw SQL仅指定了key_id和name两个字段,完全规避了冗余加载。
验证方法:用only()限制ORM返回字段,对比耗时:TenantKey.objects.only('key_id', 'name').get(pk=api_key)模型钩子/信号的额外开销
ORM查询会实例化模型对象,这会触发模型的__init__方法以及注册的信号(如post_init)。如果这些钩子函数里包含耗时操作(比如远程调用、复杂计算),会大幅增加查询耗时。而Raw SQL直接返回原始数据,不会触发这些逻辑。
验证方法:临时注释模型的自定义__init__和相关信号处理器,重新测试耗时。查询条件的隐性差异
注意到你ORM用的是pk=api_key,而Raw SQL查询的是value=%s——若TenantKey模型的主键并非value字段,这两个查询的条件完全不同:ORM会基于主键(通常是id)查询,而Raw SQL基于value查询。如果api_key实际是value的值,那ORM的查询会变成WHERE id = 'xxx',导致全表扫描(若主键不匹配还可能出现意外结果)。
验证方法:打印ORM生成的SQL语句,确认查询条件是否与Raw SQL一致:print(TenantKey.objects.filter(pk=api_key).query)对象实例化的隐性开销
即使没有关联和钩子,ORM需要把查询结果转化为TenantKey对象,涉及字段映射、属性初始化等操作。如果模型包含大量字段或复杂的property属性(实例化时自动计算),也会产生额外开销,而Raw SQL仅返回轻量的元组。
内容的提问来源于stack exchange,提问作者Kanhaya Ky

