Django ORM引發(fā)的數(shù)據(jù)庫N+1性能的原因?相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
創(chuàng)新新互聯(lián),憑借十載的網(wǎng)站設(shè)計制作、成都做網(wǎng)站經(jīng)驗,本著真心·誠心服務(wù)的企業(yè)理念服務(wù)于成都中小企業(yè)設(shè)計網(wǎng)站有超過千家案例。做網(wǎng)站建設(shè),選創(chuàng)新互聯(lián)建站。背景描述
最近在使用 Django 時,發(fā)現(xiàn)當調(diào)用 api 后,在數(shù)據(jù)庫同一個進程下的事務(wù)中,出現(xiàn)了大量的數(shù)據(jù)庫查詢語句。調(diào)查后發(fā)現(xiàn),是由于 Django ORM 的機制所引起。
Django Object-Relational Mapper(ORM)作為 Django 比較受歡迎的特性,在開發(fā)中被大量使用。我們可以通過它和數(shù)據(jù)庫進行交互,實現(xiàn) DDL 和 DML 操作.
具體來說,就是使用 QuerySet 對象來檢索數(shù)據(jù), 而 QuerySet 本質(zhì)上是通過在預(yù)先定義好的 model 中的 Manager 和數(shù)據(jù)庫進行交互。
Manager 是 Django model 提供數(shù)據(jù)庫查詢的一個接口,在每個 Model 中都至少存在一個 Manager 對象。但今天要介紹的主角是 QuerySet ,它并不是關(guān)鍵。
為了更清晰的表述問題,假設(shè)在數(shù)據(jù)庫有如下的表:
device 表,表示當前網(wǎng)絡(luò)中納管的物理設(shè)備。
interface 表,表示物理設(shè)備擁有的接口。
interface_extension 表,和 interface 表是一對一關(guān)系,由于 interface 屬性過多,用于存儲一些不太常用的接口屬性。
class Device(models.Model): name = models.CharField(max_length=100, unique=True) # 添加設(shè)備時的設(shè)備名 hostname = models.CharField(max_length=100, null=True) # 從設(shè)備中獲取的hostname ip_address = models.CharField(max_length=100, null=True) # 設(shè)備管理IP class Interface(models.Model): device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False,related_name='interfaces')) # 屬于哪臺設(shè)備 name = models.CharField(max_length=100) # 端口名 collect_status = models.CharField(max_length=30, default='active') class Meta: unique_together = ("device", "name") # 聯(lián)合主鍵 class InterfaceExtension(models.Model): interface = models.OneToOneField( Interface, on_delete=models.PROTECT, null=False, related_name='ex_info') endpoint_device_id = models.ForeignKey( # 綁定了的終端設(shè)備 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, # 綁定了的終端設(shè)備的接口 null=True, blank=True)