我有一个从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或其他东西困住?
答案 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
,或者“重新启动”光标,您只需重新选择即可。由于数据存储为“平坦”,因此重新访问应该更快。