2013-12-21 83 views
0

我有一個很大的數據集從Oracle返回,太大而不適合內存。cx_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

簡答題,沒有。

較長的答案...

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

與所有DB API的可選功能,數據庫模塊作者可以自由地不實現這些額外的屬性和方法(使用它們將導致AttributeError),或者在只能在運行時檢查可用性時引發NotSupportedError。

這只是沒有在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,或者「重新啓動」光標,您可以簡單地重新選擇。由於數據存儲「平坦」,重新訪問應該更快。