繁体   English   中英

cx_Oracle:fetchall() 停止处理大型 SELECT 语句

[英]cx_Oracle: fetchall() stops working with big SELECT statements

我正在尝试从 oracle 数据库中读取数据。 我必须在 python 上阅读返回一百万行的简单选择的结果。

我使用fetchall()函数,更改游标的 arraysize 属性。

select_qry = db_functions.read_sql_file('src/data/scripts/03_perimetro_select.sql')
dsn_tns = cx_Oracle.makedsn(ip, port, sid)
con = cx_Oracle.connect(user, pwd, dsn_tns)


start = time.time()

cur = con.cursor()
cur.arraysize = 1000
cur.execute('select * from bigtable where rownum < 10000')
res = cur.fetchall()
# print res  # uncomment to display the query results
elapsed = (time.time() - start)
print(elapsed, " seconds")
cur.close()
con.close()

如果我删除where rownum < 10000的 where 条件,python 环境会冻结并且fetchall()函数永远不会结束。

经过一些试验,我发现了这个精确选择的限制,它可以工作到 50k 行,但如果我选择 60k 行,它就会失败。

是什么导致了这个问题? 我是否必须找到另一种方法来获取这么多数据,或者问题出在 ODBC 连接上? 我怎样才能测试它?

考虑使用 Oracle 的ROWNUM批量运行。 要合并回单个对象,请附加到不断增长的列表中。 下面假设表的总行数为 1 mill。 根据需要调整:

table_row_count = 1000000
batch_size = 10000

# PREPARED STATEMENT
sql = """SELECT t.* FROM
            (SELECT *, ROWNUM AS row_num 
             FROM 
                (SELECT * FROM bigtable ORDER BY primary_id) sub_t
            ) AS t
         WHERE t.row_num BETWEEN :LOWER_BOUND AND :UPPER_BOUND;"""

data = []
for lower_bound in range(0, table_row_count, batch_size):
    # BIND PARAMS WITH BOUND LIMITS
    cursor.execute(sql, {'LOWER_BOUND': lower_bound, 
                         'UPPER_BOUND': lower_bound + batch_size - 1})

    for row in cur.fetchall():
       data.append(row)

您可能正在运行 cx_Oracle 的计算机上内存不足。 不要使用fetchall()因为这将需要 cx_Oracle 将所有结果保存在内存中。 使用类似这样的方法来获取批量记录:

cursor = connection.cursor()
cursor.execute("select employee_id from employees")
res = cursor.fetchmany(numRows=3)
print(res)
res = cursor.fetchmany(numRows=3)
print(res)

fetchmany()调用置于循环中,在获取下一组行之前处理应用程序中的每批行,并在没有更多数据时退出循环。

无论您使用什么解决方案,调整cursor.arraysize以获得最佳性能。

已经给出的重复查询和选择行子集的建议也值得考虑。 如果您使用的是 Oracle DB 12,则有一种更新(更简单)的语法,例如SELECT * FROM mytab ORDER BY id OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY

PS cx_Oracle 不使用 ODBC。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM