參考:flask-sqlalchemy中的lazy的解釋sql
SQLAlchemy的relationship( ..., lazy='??' )
方法中的lazy
參數一直是初學最容易困擾的地方。數據庫
Lazy Load Methods
是SQLAlchemy爲多表關聯而定義的一系列加載方法。爲lazy參數選擇什麼值,決定了 SQLAlchemy 何時從數據庫中加載數據。每種方法的對應着SQL語句中多表關聯的一種寫法,因此優缺點、效率高低各有不一樣。flask
lazy
參數的可選方法有:app
select
- (默認) 後臺會用select語句一次性加載全部數據,即訪問到屬性的時候,就會所有加載該屬性的數據。joined
- 數據會被JOIN語句加載,即對關聯的兩個表進行join操做,從而獲取到全部相關的對象。subquery
- 數據被用subquery子查詢SQL語句加載dynamic
- 在訪問屬性的時候,並不在內存中加載數據,而是返回一個query對象, 須要執行相應方法才能夠獲取對象。適用於數據量大的時候。immediate
- items should be loaded as the parents are loaded, using a separate SELECT statement, or identity map fetch for simple many-to-one references.noload
- no loading should occur at any time. This is to support 「write-only」 attributes, or attributes which are populated in some manner specific to the application.True
- 即 'select'方法False
- 即 'joined'方法None
- 即'noload'方法下面用School
和Students
的實例來看各類方法的不一樣。ide
假設定義兩個ORM類:函數
class School(..): id = Column(..) students = relationship( 'Student', backref='school' ) class Student(..): id = Column(..) school_id = Column(.., ForeignKey('school.id') )
上例中咱們創建了一個普通的兩表關聯:students = relationship( 'Student', backref='school' )
。
默認狀況下,參數lazy
爲select,咱們不寫也能夠)。
也就是說,若是定義lazy='select'
,那麼當咱們要進行搜索引用時(假設表中已有數據):fetch
>>> school_01 = School.query.first() # 隨便獲取一個數據庫中已有的school >>> school_01.students [ <Student: u'test'>, <Student: u'test2'>, <Student: u'test3'> ]
能夠看到,lazy='select'
會簡單直接的返回全部相關聯的數據。
可是,若是數據量很是大:好比百萬級,這種所有返回就不理智了,由於會大量侵佔內存。
因此咱們能夠選擇lazy='dynamic'
,即只返回一個query
查詢對象,供你手動加條件查詢,好比query.all()
或query.filter()
等。code
假設咱們將以前的定義改成:students = db.relationship('Student', backref='_class', lazy="dynamic")
。那麼:orm
>>> school_01.students <sqlalchemy.orm.dynamic.AppenderBaseQuery object at 0x7f007d2e8ed0> >>> print( school_01.students ) SELECT students.id AS students_id, students.name AS students_name FROM students, registrations WHERE :param_1 = registrations.class_id AND students.id = registrations.student_id >>> school_01.students.all() [ <Student: u'test'>, <Student: u'test2'>, <Student: u'test3'> ]
能夠看到, 執行school_01.students
返回的只是一個query
對象,甚至說只是返回了一條SQL
語句,就是沒有具體數據。能夠想像這個消耗的時間至關於0了。
而若是lazy=select 或者 joined
均是直接返回結果。 對象
須要注意的是,lazy="dynamic"
只能夠用在一對多和多對對關係中,不能夠用在一對一和多對一中。
這樣也合理:若是返回結果不多的話,就不必延遲加載數據了。
直接給relationship(.., lazy='??')
,只是給正向引用
設置加載方法。
實際上反向引用
也是能夠設置lazy加載方法的。
作法就是:使用backref(..)
函數:
students = relationship(..., lazy='..', backref=backref('Student, lazy='dynamic') )
能夠看到,backref(..)
函數返回的是一個backref
參數專用的值,在這裏面能夠指定反向引用的加載方法。