游标现在经过层层封装的web端业务系统,游标用的不多,但是在处理大规模数据的时候,游标还是很快的并节省内存。大大提高查询效率。假设一张数据表有1亿条记录,业务数据都需要导出或处理,显然不可能用ORMapping一次性读入内存,显然需要分段处理。常见的切分方式是通过offset+limit指定返回的记录窗口(flask-sqlalchemy直接提供了paginate对象实现分页,应该是offset+limit的封装)。这种方法很直观,但缺点也很明显:对每个段重新执行一次庞大的查询,返回的数据集只有一小部分,对数据库性能是一种巨大的浪费。这个时候应该是游标发挥作用的时候了:游标的价值在于只能执行一次查询,缓存结果位置索引,游标记录当前位置。之后每次fetch得到n条记录,游标就移动n个位置,从而节省了大量的磁盘IO。从实现原理上来说,Cursor分为服务端游标和客户端游标。区别在于结果集索引的缓存位置。服务器端缓存允许多个连接共享结果集,数据库的内存配置往往很高;但是,目前的数据库客户端一般都是应用服务器,内存配置不低。做客户端缓存有助于分担服务器的压力。SQLAlchemy的默认连接是客户端缓存。如果sqlalchemy获取游标,从网上搜索,通常找到的代码是这样的:engine=create_engine('sqlite:///file.db')connection=engine.connect()try:cursor_obj=connection.cursor()cursor_obj.execute("select*fromtable1")results_one=cursor_obj.fetchall()cursor_obj.close()finally:connection.close()或者用raw_connection代替connection,但是如果我们在web环境下,就用flask之类的东西-sqlalchemy环境,显然你不能自己管理数据库连接,应该统一管理所有的事务,所以你需要从会话中获取连接:db=SQLAlchemy()db.init_app(app)session=db.session()cursor=session.execute('select*fromuserlimit10').cursorresult=cursor.fetchall()print(result)使用游标获取数据获取到游标后,可以使用游标获取数据。请注意,光标只能按顺序从前向后移动。回头再拿是不可能的,所以fetch的动作就是拿数据,移动游标。fetch方法一共有三种:fetchone()、fetchmany(size)和fetchall(),顾名思义,分别取一条记录、多条记录和所有记录。fetchmany和fetchall得到的结果集是一个嵌套的tuple,第一层是rows,第二层是columns;又因为fetchone已经明确表示只有一条记录,所以结果集是单层元组。例如,假设用户表有四个字段id|帐户|姓名|注释以下代码:cursor=session.execute('select*fromuserlimit10').cursorresult=cursor.fetchmany(2)print(result)result=cursor.fetchmany(2)print(result)result=cursor.fetchone()print(result)result=cursor.fetchall()输出类似于以下内容:((1,'acc1','acc1',None),(2,'acc2','acc2',None))((3,'acc3','acc3',无),(4,'acc4','acc4',无))(5,'acc6','acc6',无)((6,'acc7','acc7',无),(7,'acc8','acc8',无),(8,'acc9','acc9',无),(9,'acc10','acc10',无),(10,'acc11','acc11',无))
