SQLAlchemy 在 select 语句上占用内存

2023-11-24

根据 SQLAlchemy,select 语句被视为 for 循环中的可迭代对象。其效果是,返回大量行的 select 语句不会使用过多的内存。

我发现 MySQL 表上有以下语句:

for row in my_connections.execute(MyTable.__table__.select()):
    yield row

似乎没有遵循这一点,因为我溢出了可用内存并在产生第一行之前开始抖动。我究竟做错了什么?


基础的MySQLdb游标一次从服务器获取整个查询结果。 这会消耗大量内存和时间。 使用MySQLdb.cursors.SSCursor当你想要进行一个巨大的查询并且 一次从服务器提取一个结果。

因此,尝试通过connect_args={'cursorclass': MySQLdb.cursors.SSCursor}创建时engine:

   from sqlalchemy import create_engine, MetaData
   import MySQLdb.cursors
   engine = create_engine('mysql://root:zenoss@localhost/e2', connect_args={'cursorclass': MySQLdb.cursors.SSCursor})
   meta = MetaData(engine, reflect=True)
   conn = engine.connect()
   rs = s.execution_options(stream_results=True).execute()

See http://www.sqlalchemy.org/trac/ticket/1089


请注意,使用 SSCursor 会锁定表,直到获取完成。这会影响使用同一连接的其他游标:来自同一连接的两个游标不能同时从表中读取。

但是,来自不同连接的游标可以同时读取同一个表。

这是一些演示该问题的代码:

import MySQLdb
import MySQLdb.cursors as cursors
import threading
import logging
import config

logger = logging.getLogger(__name__)
query = 'SELECT * FROM huge_table LIMIT 200'

def oursql_conn():
    import oursql
    conn = oursql.connect(
        host=config.HOST, user=config.USER, passwd=config.PASS,
        db=config.MYDB)
    return conn

def mysqldb_conn():
    conn = MySQLdb.connect(
        host=config.HOST, user=config.USER,
        passwd=config.PASS, db=config.MYDB,
        cursorclass=cursors.SSCursor) 
    return conn

def two_cursors_one_conn():
    """Two SSCursors can not use one connection concurrently"""
    def worker(conn):
        cursor = conn.cursor()
        cursor.execute(query)
        for row in cursor:
            logger.info(row)

    conn = mysqldb_conn()
    threads = [threading.Thread(target=worker, args=(conn, ))
               for n in range(2)]
    for t in threads:
        t.daemon = True
        t.start()
        # Second thread may hang or raise OperationalError:
        # File "/usr/lib/pymodules/python2.7/MySQLdb/cursors.py", line 289, in _fetch_row
        #   return self._result.fetch_row(size, self._fetch_type)
        # OperationalError: (2013, 'Lost connection to MySQL server during query')

    for t in threads:
        t.join()

def two_cursors_two_conn():
    """Two SSCursors from independent connections can use the same table concurrently"""    
    def worker():
        conn = mysqldb_conn()        
        cursor = conn.cursor()
        cursor.execute(query)
        for row in cursor:
            logger.info(row)

    threads = [threading.Thread(target=worker) for n in range(2)]
    for t in threads:
        t.daemon = True
        t.start()
    for t in threads:
        t.join()


logging.basicConfig(level=logging.DEBUG,
                    format='[%(asctime)s %(threadName)s] %(message)s',
                    datefmt='%H:%M:%S')
two_cursors_one_conn()
two_cursors_two_conn()

注意oursql是 Python 的一组替代 MySQL 绑定。 oursql 游标是真正的服务器端游标默认情况下延迟获取行. With oursql已安装,如果您更改

conn = mysqldb_conn()

to

conn = oursql_conn()

then two_cursors_one_conn()运行时不会挂起或引发异常。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SQLAlchemy 在 select 语句上占用内存 的相关文章

随机推荐

  • 如何在 Ruby on Rails 上制作“数据透视表”?

    首先 我想提一下 我对 Ruby 和 Rails 完全陌生 我才刚开始学习 所以如果我的问题看起来有点不清楚或太宽泛 我深表歉意 我正在尝试做一些简单的事情 我认为 即旋转表格 我有一个看起来像这样的表 Name Product ID Am
  • 使用颜色图作为第四维(x、y、z 的函数)绘制 3D 表面

    我正在尝试绘制一个 3d 表面 其中三个维度中的每一个都位于单独的值数组中 并且每个坐标处的表面颜色是 x y z 的函数 一种 numpy pcolormesh 但是 4D 而不是 3D 3D 图由下式给出 from mpl toolki
  • 在 Delphi 中查找未使用的(又名“死的”)代码

    是否有任何工具可以确定是否使用了函数 过程 方法 整个类 我见过一些工具可以帮助知识渊博的开发人员追踪未使用的代码片段 大多数适用于 Delphi 以外的语言 但大多数都有一个陡峭的学习曲线和 或需要大量的挖掘来确定是否使用了代码片段 据称
  • 使用 pandas read_html 提取 href

    作为我工作的一部分 我需要检查这个page定期获取特定文件 我发现我可以使用 pandas 的方法read html成功地将表读入数据帧 这很方便 因为我可以轻松地通过关键字查询特定文档 我现在遇到的问题是 此方法无法解析我需要的链接 而是
  • Windbg 首先连接,然后卡在“调试对象未连接”上。内核调试期间的消息

    我正在尝试进行 Windows 内核调试 因此我为此目的设置了两台机器 HOST DEBUGGER 运行windbg调试器的计算机 TARGET DEBUGEE 正在调试的计算机 HOST 和 TARGET 都运行 Windows 7 32
  • 按钮背景选择器

    如果按下按钮 我尝试切换按钮的背景 我构建了一个选择器 就像这里建议的答案一样 具有不同颜色的标准 Android 按钮 最后我想放GradientDrawables在里面 但出于调试目的 我只是设置了一种颜色 以检查它是否有效 这是我的选
  • 从 HTMLDocument 获取所有 html 作为字符串

    我用 Java 编码 有谁知道我如何获取 javax swing text html HTMLDocument 的内容作为字符串 这就是我到目前为止所得到的 URL url new URL http www test com HTMLEdi
  • MySQL 用户定义函数

    我有一个表包含几列 column 1 column 2 和column 3 我将一个新列添加到名为 分数 的表中 我想做的是根据这三列计算分数并轻松调整参数 假设我的分数公式如下所示 score a column 1 b column 2
  • 动态更改 gridview 横轴计数以填充 flutter 中的动态列

    我正在使用 flutter 框架开发 gridview 以实现动态列计数 但没有得到解决方案 我尝试过将 GridView count 和 Gridview builder 与 itembuilder 一起使用 但没有得到预期的结果 任何帮
  • PHP:如何将时间字符串与日期('H:i')进行比较?

    我将时间保存在数据库中 例如晚上 7 30 作为 varchar 字段 我想检查这个时间是否大于现在的时间 我将数据库时间字符串转换为 19 30 现在我想做这样的事情 my time 19 30 if my time gt date H
  • 是否可以在 Chart.js 中生成圆形雷达图?

    当我绘制标准 Chart js 雷达图时 轴是多边形 不是圆形 例如 是否可以将轴做成圆形 像这样 编辑 2021 10 27 Chart js v3已删除scale有利于的选择options scales r 这是使雷达网格呈圆形的更新方
  • 多线程 ViewController 中的 UIWebView

    我在视图控制器中有一个 UIWebView 它有以下两种方法 问题是 如果我在第二个线程完成之前弹出 重新点击导航栏 此控制器 应用程序将在 super dealloc 之后崩溃 因为 尝试从主线程以外的线程获取 Web 锁或Web 线程
  • 调用init方法失败;嵌套异常是 java.lang.IllegalArgumentException:方法公共抽象的查询验证失败

    我正在开发Spring MVC Spring data jpa querydsl我是新手 当我为 querydsl 编写代码时 在该代码工作正常之前 当我添加 querydsl 相关代码时 我开始收到以下错误 不确定出了什么问题 请指导 错
  • 如何为同一个函数设置不同的输入类型?

    我想做的基本想法是 def aFuncion string dicti if len str gt 0 print you gave string as input if len dicti gt 0 print you gave a di
  • 从我的应用程序登录 Facebook 可以在模拟器上运行,但不能在设备上运行

    这是我登录 Facebook 的代码 mLoginButton LoginButton findViewById R id login restore session if one exists SessionStore restore U
  • Firefox 无法正确显示 :before 和 :after 伪元素

    在除 Firefox 之外的所有其他浏览器上 网页看起来都很好 甚至是 Internet Explorer 伪元素漂浮在整个文档中 甚至在第一个元素显示后不显示 这种行为有什么解决办法吗 CSS span property dc date
  • 如何使用 php 编辑/更新 txt 文件

    在我阅读了文件上的编辑 更新功能的很多类似问题并且没有一个起作用之后 我想寻求一些帮助 我正在尝试编辑 txt来自 php ini 的文档我已经尝试过这些事情 这是我在这里阅读的最后一个代码 但它不起作用 data to write POS
  • ARM 汇编器 - 如何使用 CMP、BLT 和 BGT?

    问你们一个简单的问题 在我的循环中 我需要使用 CMP BLT 和 BGT 来比较一些值 如何在下面的循环中使用所述指令 我正在尝试使用 BGT BLT 和 CMP 因为我需要它们来使我的应用程序正常工作 问题是我不知道如何使用它们 如果我
  • 我可以传递 --max-concurrent-downloads 作为标志吗?

    我正在使用较差的互联网连接并尝试拉取并运行图像 我想一次下载一层 每个文档尝试添加一个平面 max concurrent downloads 如下所示 docker run rm p 8787 8787 e PASSWORD blah ma
  • SQLAlchemy 在 select 语句上占用内存

    根据 SQLAlchemy select 语句被视为 for 循环中的可迭代对象 其效果是 返回大量行的 select 语句不会使用过多的内存 我发现 MySQL 表上有以下语句 for row in my connections exec