❖ SQLAlchemy进阶:Lazy Load 加载参数

参考:flask-sqlalchemy中的lazy的解释

SQLAlchemy的relationship( ..., lazy='??' )方法中的lazy参数一直是初学最容易困扰的地方。

Lazy Load Methods是SQLAlchemy为多表关联而定义的一系列加载方法。为lazy参数选择什么值,决定了 SQLAlchemy 什么时候从数据库中加载数据。每种方法的对应着SQL语句中多表关联的一种写法,所以优缺点、效率高低各有不同。

lazy参数的可选方法有:

  • 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'方法

下面用SchoolStudents的实例来看各种方法的不同。

假设定义两个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',那么当我们要进行搜索引用时(假设表中已有数据):

>>> 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()等。

假设我们将之前的定义改为:students = db.relationship('Student', backref='_class', lazy="dynamic")。那么:

>>> 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"只可以用在一对多和多对对关系中,不可以用在一对一和多对一中。

这样也合理:如果返回结果很少的话,就没必要延迟加载数据了。

backref(..., lazy=...) 反向引用的lazy加载

直接给relationship(.., lazy='??'),只是给正向引用设置加载方法。
实际上反向引用也是可以设置lazy加载方法的。
做法就是:使用backref(..)函数:

    students = relationship(..., lazy='..', backref=backref('Student, lazy='dynamic') )

可以看到,backref(..)函数返回的是一个backref参数专用的值,在这里面可以指定反向引用的加载方法。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容