cx_Oracle是否支持可滚动游标?

时间:2013-12-21 08:55:42

标签: python oracle cursor cx-oracle

我有一个从Oracle返回的大型数据集,太大而无法放入内存。

我需要多次重新遍历整个数据集。

由于数据集的大小,一直无法重新运行查询。

有没有办法从Oracle访问可滚动的Cursor?我正在使用cx_Oracle。

在PostgreSQL中,我可以cursor.scroll(0, mode='absolute')将光标发送回数据集的开头。

Google建议OCI 8支持可滚动的客户端游标,并且有C示例用于构造这样的游标。 cx_Oracle documentation未显示Cursor.scroll方法,即使它已被指定为DB-API 2.0的一部分。

我是否会被使用pyodbc或其他东西困住?

1 个答案:

答案 0 :(得分:1)

简短回答,不。

更长的答案......

虽然Cursor.scroll()被指定为PEP 249的一部分,但它在Optional DB API Extensions部分引用:

  

与所有DB API可选功能一样,数据库模块作者可以自由地不实现这些附加属性和方法(使用它们会导致AttributeError)或者在只能在运行时检查可用性时引发NotSupportedError -time。

但是,这根本没有在cx_Oracle中实现,正如你所说,它是possible with OCI

你提到数据集太大而无法容纳到内存中,我假设你的意思是客户端?您是否考虑让数据库承担负担?您没有提到您的查询是什么,有多复杂,实际返回了多少数据等,但您可以考虑caching the result-set。这里有一些选项,无论如何数据库和操作系统都会在后台执行,但主要的选择是使用RESULT_CACHE hint

select /*+ result_cache */ ...
  from ...

您可以使用的内存量基于RESULT_CACHE_MAX_SIZE初始化参数,您可以通过运行以下查询找到该值

select *
  from v$parameter
 where name = 'result_cache_max_size'

这有多大取决于您的数据库正在进行的工作量,参数的大小等。主题上有a lot of information

另一种选择可能是使用global temporary table (GTT)来保留结果。使用光标将数据插入GTT,然后选择变为

select * from temp_table

我可以看到一个主要的好处,你可以通过行的索引来访问表,就像你想要使用可滚动游标一样。使用附加列声明您的表,以指示索引:

create global temporary table temp_table (
    i number
  , col1 ...
  , primary key (i)
    ) on commit delete rows

然后使用ROWNUM psuedocolumn插入其中以创建与Python中相同的“索引”:

select rownum - 1, c.*
  from cursor c

要访问0 th 行,您可以添加谓词WHERE i = 0,或者“重新启动”光标,您只需重新选择即可。由于数据存储为“平坦”,因此重新访问应该更快。