代码之家  ›  专栏  ›  技术社区  ›  paolof89

cx_oracle:获取所有停止点以使用大选择指令

  •  1
  • paolof89  · 技术社区  · 7 年前

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

    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条件 where rownum < 10000 python环境冻结,而 fetchall() 功能永无止境。

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

    是什么导致了这个问题?我是否必须找到另一种方法来获取这么多的数据,或者问题是ODBC连接?我如何测试它?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Christopher Jones    7 年前

    运行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() 在循环中调用,在获取下一组行之前处理应用程序中的每批行,并在没有更多数据时退出循环。

    你用什么解决方案,tune cursor.arraysize

    SELECT * FROM mytab ORDER BY id OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY .

        2
  •  2
  •   Parfait    7 年前

    考虑使用Oracle的 ROWNUM

    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)