Sqlalchemy-查询和query.all-in for循环之间的差异

Sqlalchemy-查询和query.all-in for循环之间的差异,sqlalchemy,Sqlalchemy,我想问一下两者之间的区别是什么 for row in session.Query(Model1): pass 及 第一个是一个迭代器,用单个查询轰炸您的数据库,而后一个“急切”的查询则以列表的形式(比如范围(x)与范围(x))?不,数据库流量没有区别。区别在于,对于session.Query(Model1)中的行,在ORM将要给您的每一行上都执行ORM操作,而对于session.Query(Model1)中的行,

我想问一下两者之间的区别是什么

for row in session.Query(Model1):
    pass


第一个是一个迭代器,用单个查询轰炸您的数据库,而后一个“急切”的查询则以列表的形式(比如范围(x)与范围(x))?

不,数据库流量没有区别。区别在于,
对于session.Query(Model1)中的行,
在ORM将要给您的每一行上都执行ORM操作,而
对于session.Query(Model1)中的行,
在开始给您之前对所有行执行ORM操作

请注意,
q.all()
只是
list(q)
的糖,即将生成器生成的所有内容收集到一个列表中。以下是在
查询
类中(在链接的源代码中查找
defall
中)对它的定义:

。。。其中,查询对象
self
是一个iterable,即具有一个
\uuuuuuuuuuuuuu
方法

所以从逻辑上讲,这两种方式在DB流量方面是完全相同的;最后都调用了
query.\uu iter\uu()
来获得一个行迭代器,而
next()
则通过它们来完成


实际的区别是,前者可以在数据到达后立即开始给您行,“流式”将DB结果集提供给您,从而减少内存使用和延迟。我不能肯定当前所有的引擎实现都能做到这一点(我希望他们能做到!)。在任何情况下,后一个版本都会阻止这种效率,这是没有充分理由的。

不,DB流量没有区别。区别在于,
对于session.Query(Model1)中的行,
在ORM将要给您的每一行上都执行ORM操作,而
对于session.Query(Model1)中的行,
在开始给您之前对所有行执行ORM操作

请注意,
q.all()
只是
list(q)
的糖,即将生成器生成的所有内容收集到一个列表中。以下是在
查询
类中(在链接的源代码中查找
defall
中)对它的定义:

。。。其中,查询对象
self
是一个iterable,即具有一个
\uuuuuuuuuuuuuu
方法

所以从逻辑上讲,这两种方式在DB流量方面是完全相同的;最后都调用了
query.\uu iter\uu()
来获得一个行迭代器,而
next()
则通过它们来完成


实际的区别是,前者可以在数据到达后立即开始给您行,“流式”将DB结果集提供给您,从而减少内存使用和延迟。我不能肯定当前所有的引擎实现都能做到这一点(我希望他们能做到!)。在任何情况下,后一个版本都没有充分的理由阻止这种效率。

事实上,接受的回答不是真的(或者至少不再是真的,如果是真的话),特别是以下陈述是假的:

(1) 区别在于,对于session.Query(Model1)中的行,当它将要向您提供每一行时,ORM会对每一行进行处理,而对于session.Query(Model1)中的行,all()会在开始向您提供这些行之前对所有行进行ORM处理

SQLAlchemy将始终ORM映射所有行,无论您选择使用两个选项中的哪一个。这可以在他们的源代码中看到;
load.instances
方法确实会返回一个生成器,但返回一个已经映射的ORM实例;您可以在以下文件中确认这一点:

对于行中的行:#`rows``这里已经有ORM映射的行
产量行
因此,当生成器的第一次运行完成并生成一个实例时,所有实例都已映射。(举例如下(1))

(2) 实际的区别是,前者可以在数据到达后立即开始给您行,“流式”将DB结果集提供给您,从而减少内存使用和延迟

如上所述,这也是错误的,因为在进行任何屈服之前将进行处理/映射

这些评论也具有误导性。具体而言:


数据库命中可能是相同的,但请记住,all将把整个结果集加载到内存中。这可能是千兆字节的数据

无论是否使用
.all()
,都将加载整个结果集。从中可以清楚地看到。这也很容易测试/验证

我能从所述的两个选项中看到的唯一区别是,通过使用
.all
,您将在结果中循环两次(如果您想处理所有实例/行),因为首先通过调用
list(self)
将生成器迭代/耗尽,以将其转换为列表

由于SQLAlchemy代码不容易理解,我写了一个简短的代码片段来举例说明这一切:

类查询:
def all(自我):
返回列表(自我)
def实例(self,行到取数=5):
“”“ORM实例生成器”“”
映射的_行=[]
对于范围内的i(行到提取):
#ORM映射在这里工作,如loading.instances的第81-88行所示
映射的_行。追加(i)
打印(“所有行的orm工作已完成”)
对于映射_行中的行:#与``映射_行的产量`相同``
打印(“产量行”)
产量行
定义(自我):
返回self.instances()
query=query()
打印(“(1)生成器场景:”)
打印(“发生器的第一项:”,下一项(iter(查询)))
打印(“\n(2)列表方案:”)
打印(“列表的第一项:”,query.all()[0])
"""
结果:
--------
(1) 生成器场景:
所有行的orm工作都已完成
产量行
生成器的第一项:0
(2) 列出场景:
所有行的orm工作都已完成
产量行
产量行
产量行
产量行
产量行
列表的第一项:0
"""
为了在处理大型结果集时拥有更精细的控制,我们必须使用类似于示例的方法,但这不是一个逐个案例的场景,而是一批批实例地执行ORM映射
for row in session.Query(Model1).all():
    pass
def all(self):
    """Return the results represented by this ``Query`` as a list.

    This results in an execution of the underlying query.

    """
    return list(self)