Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python SQLAlchemy内存hog on select语句_Python_Sqlalchemy - Fatal编程技术网

Python SQLAlchemy内存hog on select语句

Python SQLAlchemy内存hog on select语句,python,sqlalchemy,Python,Sqlalchemy,根据SQLAlchemy,select语句在for循环中被视为iterables。其效果是,返回大量行的select语句不会占用过多内存 我在MySQL表上发现以下语句: for row in my_connections.execute(MyTable.__table__.select()): yield row 似乎没有遵循这一点,因为我溢出了可用内存,并在产生第一行之前开始抖动。我做错了什么?基本的MySQLdb游标立即从服务器获取整个查询结果。 这会消耗大量内存和时间。 当您想

根据SQLAlchemy,select语句在for循环中被视为iterables。其效果是,返回大量行的select语句不会占用过多内存

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

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

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

基本的
MySQLdb
游标立即从服务器获取整个查询结果。 这会消耗大量内存和时间。 当您想要进行大型查询和 从服务器一次提取一个结果

因此,请尝试传递
connect_args={'cursorclass':MySQLdb.cursors.SSCursor}
创建
引擎时

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


请注意,使用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()
请注意,这是Python的另一组MySQL绑定。我们的SQL游标是真正的服务器端游标。安装了
oursql
,如果您更改

conn = mysqldb_conn()


然后,
two\u cursors\u one\u conn()
运行时不会挂起或引发异常。

这解决了MySQL的内存问题,并产生了每个。你知道为什么Trac上的回复说这“几乎没用了”@b库伦:我添加了一些代码,并讨论了并发使用SSCursors的限制。这应该可以解决mysqldb的问题,mysqlconnector是否有类似的选项,因为我在使用该驱动程序时面临类似的问题。@Yogessajanikar:我对mysqlconnector不太熟悉,但据报道,mysql连接器中还没有服务器端游标。解决方法是以块的形式获取数据。
conn = oursql_conn()