2012-08-06 61 views
0

最近我提出了一個問題。我們希望批量獲取Oracle數據庫中的數據表,其中一個批處理例如是4-5000。我以前的「一般」的解決辦法是選擇到包裝成某種如下的東西:Oracle中緩慢的內部N選擇

SELECT * FROM (
    SELECT ROWNUM AS RN, INNERSELECT.* FROM (
     select THINGS1, THINGS2 from MYTABLE) 
    ) 
INNERSELECT WHERE ROWNUM < 4001) WHERE RN >= 3001 

似乎是緩慢,因爲當ROWNUM邊界高(例如4-500.000),則選擇將超過10-20秒。隨着數值的增加,時間線性增加。當然,我知道爲什麼,所以我想找到另一種解決方案來批量獲取數據,但需要一定的時間。好了然後我用這樣的選擇:

SELECT * FROM (
    SELECT INNERSELECT.*, ROW_NUMBER() OVER (ORDER BY INNERSELECT.ROWID) RN FROM 
    (select THINGS1, THINGS2 from MYTABLE) 
    INNERSELECT 
) WHERE RN BETWEEN 3001 AND 4000; 

這是一個有點慢(過了3-4秒,以獲得測試批量數據的),但我可能會增加不noticable性能下降批量大小高價值也是一樣。 當前問題是我從數據庫的多個線程中的多個表中進行選擇,如果我只使用3個線程(並且我們沒有談論當前用於項目的16),則性能下降到地獄。 JDBC連接被集中,性能下降在服務器端。我認爲很明顯,這個選擇正在吃掉CPU時間,所以我什麼都做不了,但是我希望你們都有一些提示或者提示,以便如何優化。

另一個問題是,我們用的是不是項目的具體工具,它必須是一般地,所以我不能使用複製表例如,等事先

感謝您的答案

回答

1

假設MYTABLE有一個數字主鍵ID,一個戰術就是讓每一個16個線程的執行這個查詢:

SELECT THINGS1, THINGS2 
FROM MYTABLE 
WHERE MOD(ID,15) = :THREAD_NUMBER 

每個線程會從0獲得:THREAD_NUMBER唯一值15。這意味着,每個線程將獲得(大約)1/16行。

+0

我相信這將導致每個編號線程的全表掃描。避免這種情況的最好方法是在MYTABLE上使用一些分區。 – OraNob 2012-08-06 22:14:58

+0

理想情況下,是的,數據將被分區,或者索引列被查詢並且索引可以被全面掃描。 – 2012-08-06 22:24:03

+0

這是一個很好的改進。謝謝。 – newhouse 2012-08-22 08:24:44

0
SELECT * FROM (
    SELECT INNERSELECT.*, ROW_NUMBER() OVER (ORDER BY INNERSELECT.ROWID) RN FROM 
    (select THINGS1, THINGS2 from MYTABLE) 
    INNERSELECT 
) WHERE RN BETWEEN 3001 AND 4000; 

(從MYTABLE選擇THINGS1,THINGS2)

多少行這是否檢索? 如果您可以在此處放置某種限制條款 - 這將避免系統必須執行FULL TABLE SCAN或INDEX SCAN。

ORDER BY INNERSELECT.ROWID

是否有必要發出這種?特別是因爲排序標準是系統生成的值。 大量排序可能會對數據庫產生巨大影響。

要記住的重要一點是在Oracle中使用ROWNUM記錄提取 - 數據庫,但一個ORDER BY之前應用ROWNUM的記錄作爲的最後的事情之一〜。