sqlalchemy 的查询机制?

用 sqlalchemy 进行简单的查询:


# -*- coding:utf-8 -*-
__author__ = '东方鹗'
__blog__ = 'http://www.os373.cn'

from models import session, Employee, Department, DeptEmp, DeptManager, Salary, Title

# 初始化数据库连接:
engine = create_engine('mysql+pymysql://root:password@127.0.0.1:3306/employees', echo=True)
# 创建DBSession类型:
DBSession = sessionmaker(bind=engine)
session = DBSession

data = session.query(Employee).all()
session.commit()

for d in data:
    print(d.emp_no, d.birth_date, d.first_name, d.last_name, d.gender, d.hire_date)

然后打印出来的结果如下:

图片描述

根据图片所示,难道 sqlalchemy 把所有的内容查询出来之后,如果要显示每条的明细,还得从数据库里一条一条的查询出来吗???

阅读 4.9k
3 个回答

原来,加上all()会出现一条一条再查询的问题,如果不加则没有该问题?
不过对于 flask 如果你加上分页,然后通过人工来一页页的查询,倒是也不怎么影响性能!!!

sqlalchemy把所有内容查询出来后,显示明细,确实是还需要从数据库中一条一条的查询出来。
只不过这个查询不是从物理db中查询,而是从虚拟内存db中查询。
(注:以下说法均为个人从日常实践及对sqlalchemy的理解中得出的,官方具体怎么样没有实际佐证)

create_engine时会调用create_all()方法,这时将会在内存中创建一个虚拟数据库表。
查询操作会将数据库中的数据加载至内存,调用明细时会对内存中的表进行查询操作。

# 1. 类似于下面的这种操作是不会触发物理db的相关操作的,只是生成一段用于在物理db中执行的sql
query_str = Model.query.filter(...).order_by(...).with_entities(...)

# 2. query_str执行get()、all()、first()、one_or_none()等操作时,才会在链接物理db并执行操作。
# 3. sqlalchemy会将返回结果保存至内存中,最为缓存,供用户查询相关明细。
# 4. 至于查询明细的方式,本质上估计类似于dict.get(key)这种,具体的要看sqlalchemy以什么数据结构
# 在内存中保存查询信息了,个人未关注过
# 5. db.commit()操作会触发类似flush()的操作,这时会将缓存中的信息清空。例:
# 会在物理db中执行select * from model where id = 1;
result = Model.query.get(1)
# 内存中去查询name,不会涉及到物理db
print result.name
# 内存清空
db.commit()
# 两步操作,①select * from model where id = 1;②从内存中去拿name
print result.name

# 注:for循环等遍历操作会默认触发all()方法,例:
# 生成sql,select * from model;但未与物理db有相关交互。
query = Model.query
# 等价于 for res in query.all(),在物理db中执行相关sql
for res in query:
# 从内存中查询id
print res.id

# 刚上边那段瞎说了,请忽略,下面为更正信息
# 生成sql,select * from model;但未与物理db有相关交互。
# query现在为一个str,及query = 'select * from model'
query = Model.query
# 等价于 for res in query.all(),在物理db中执行相关sql
# 现假设query中有三个结果[res1, res2, res3]
# 执行完后query为查询结果集合,query=[res1, res2, res3]
for res in query:
  # 从内存中查询id
  print res.id
# 清空缓存,但[res1, res2, res3]对象是保留的,及query=[res1, res2, res3]
db.commit()
# 等价于 for res in [res1, res2, res3]:
for res in query:
  # 两部操作:①select * from model where id = res.id,从内存中查询id
  # 及commit后res1为detached状态,res.id后为attached状态
  print res.id

在SQLAlchemy中一个Session(可以看作)是一个transaction,每个操作(基本上)对应一条或多条SQL语句,这些SQL语句需要发送到数据库服务器才能被真正执行,
附上大佬链接https://segmentfault.com/q/10...

推荐问题
宣传栏