【问题标题】:cx_Oracle: How do I iterate over a result set?cx_Oracle:如何迭代结果集?
【发布时间】:2010-09-05 06:17:17
【问题描述】:

有几种方法可以迭代结果集。各自的取舍是什么?

【问题讨论】:

  • 这也有例外,但一般的经验法则是:如果有不止一种方法可以做到,那可能是因为每种方法都适合不同的情况。否则只有一种方式。

标签: python sql database oracle cx-oracle


【解决方案1】:

规范的方法是使用内置的游标迭代器。

curs.execute('select * from people')
for row in curs:
    print row

您可以使用fetchall() 一次获取所有行。

for row in curs.fetchall():
    print row

使用它来创建一个包含返回值的 Python 列表会很方便:

curs.execute('select first_name from people')
names = [row[0] for row in curs.fetchall()]

这对于较小的结果集很有用,但如果结果集很大,则可能会产生不良的副作用。

  • 您必须等待整个结果集返回到 您的客户端进程。

  • 您可能会占用客户端的大量内存来保存 构建列表。

  • Python 可能需要一段时间来构建和解构 列出您无论如何都要立即丢弃的列表。


如果您知道结果集中返回了单行,您可以调用 fetchone() 来获取单行。

curs.execute('select max(x) from t')
maxValue = curs.fetchone()[0]

最后,您可以循环遍历结果集,一次获取一行。一般来说,这样做比使用迭代器没有特别的优势。

row = curs.fetchone()
while row:
    print row
    row = curs.fetchone()

【讨论】:

  • 关于第二种方法,如果你使用 SScursor 怎么办?它还会吃掉很多内存吗?
  • 我认为 SScursor 适用于 MySQL。但是任何具有 fetchall() 的东西都可能具有相同的内存使用情况,因为它会返回所有返回行的列表。
【解决方案2】:

我首选的方式是游标迭代器,但首先设置游标的arraysize 属性。

curs.execute('select * from people')
curs.arraysize = 256
for row in curs:
    print row

在此示例中,cx_Oracle 将一次从 Oracle 中获取 256 行,从而减少需要执行的网络往返次数

【讨论】:

  • 在我的测试中(在通过 LAN 连接的数据库上),与重复执行 'fetchone()' 相比,这实际上似乎给出了相同的速度(甚至更慢,在几次迭代中)。我用大约 12000 个条目来做这件事……很奇怪!
  • 我知道的唯一方法,而且我绝不是 Oracle 专家,如果您的查询返回字符大对象 (CLOB) 或二进制大对象 ( BLOB) 类型。 AFAI 明白了,读取这些对象需要为每条记录再一次网络往返到 db 服务器;这意味着使用 fetchmany 你实际上得到了两全其美的结果。
  • 对于 cx_Oracle,连接到具有标准列类型(没有 clob 等)的 12c 数据库我得到了加速,但前提是我在执行查询之前设置了 arraysize。精确的数字显然很大程度上取决于上下文,但为了了解数量级的变化,我的查询(返回 5 列)arraysize=50(默认)给出了每行 3.75us。将 arraysize 减小到 1 会产生 70us。将数组大小增加到 1000 会得到 800ns
  • @FredL 我看到了类似的东西。 只有在调用execute 之前设置才会产生影响。
【解决方案3】:

psyco-pg 似乎也有这样做的方式...据我所知,它似乎创建了类似字典的行代理,以将键查找映射到查询返回的内存块。在这种情况下,获取整个答案并在行上使用类似的代理工厂似乎很有用。不过仔细想想,感觉更像是 Lua 而不是 Python。

此外,这应该适用于所有PEP-249 DBAPI2.0 接口,而不仅仅是Oracle,或者您的意思是最快 使用Oracle

【讨论】:

    猜你喜欢
    • 2020-01-02
    • 2016-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-07
    • 2021-09-29
    • 1970-01-01
    相关资源
    最近更新 更多