重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
Django ORM引发的数据库N+1性能的原因?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
创新新互联,凭借十载的网站设计制作、成都做网站经验,本着真心·诚心服务的企业理念服务于成都中小企业设计网站有超过千家案例。做网站建设,选创新互联建站。背景描述
最近在使用 Django 时,发现当调用 api 后,在数据库同一个进程下的事务中,出现了大量的数据库查询语句。调查后发现,是由于 Django ORM 的机制所引起。
Django Object-Relational Mapper(ORM)作为 Django 比较受欢迎的特性,在开发中被大量使用。我们可以通过它和数据库进行交互,实现 DDL 和 DML 操作.
具体来说,就是使用 QuerySet 对象来检索数据, 而 QuerySet 本质上是通过在预先定义好的 model 中的 Manager 和数据库进行交互。
Manager 是 Django model 提供数据库查询的一个接口,在每个 Model 中都至少存在一个 Manager 对象。但今天要介绍的主角是 QuerySet ,它并不是关键。
为了更清晰的表述问题,假设在数据库有如下的表:
device 表,表示当前网络中纳管的物理设备。
interface 表,表示物理设备拥有的接口。
interface_extension 表,和 interface 表是一对一关系,由于 interface 属性过多,用于存储一些不太常用的接口属性。
class Device(models.Model): name = models.CharField(max_length=100, unique=True) # 添加设备时的设备名 hostname = models.CharField(max_length=100, null=True) # 从设备中获取的hostname ip_address = models.CharField(max_length=100, null=True) # 设备管理IP class Interface(models.Model): device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False,related_name='interfaces')) # 属于哪台设备 name = models.CharField(max_length=100) # 端口名 collect_status = models.CharField(max_length=30, default='active') class Meta: unique_together = ("device", "name") # 联合主键 class InterfaceExtension(models.Model): interface = models.OneToOneField( Interface, on_delete=models.PROTECT, null=False, related_name='ex_info') endpoint_device_id = models.ForeignKey( # 绑定了的终端设备 Device, db_column='endpoint_device_id', on_delete=models.PROTECT, null=True, blank=True) endpoint_interface_id = models.ForeignKey( Interface, db_column='endpoint_interface_id', on_delete=models.PROTECT, # 绑定了的终端设备的接口 null=True, blank=True)