2017-09-29 5 views
0

Oracle 11.2を使用していますが、何百万行もの表を持つ表にページング問合せを書き込もうとしています。他の記事を読む私は最良のアプローチを見つけたと思うが、ページ番号が高いほど速度が遅くなる。プライマリ・キーのリストを使用した大規模な表のOracleページング

これは私のソリューションです。最初に、そのデータページの主キー値(ID)のリストを取得します。私はそれらのIDに一致する他のすべてのテーブルデータを取得します。しかし、これはまだゆっくりと実行されます。

​​3210

実行時間:30秒以上。

私は、内側のクエリを実行する場合は、別途、手動で、それははるかに高速だ外部クエリにIDを渡します

SELECT ID 
FROM (
    SELECT ID, ROWNUM rnum 
    FROM (
     SELECT ID 
     FROM mytable 
     ORDER BY ID 
    ) results 
    WHERE ROWNUM <= 1000010 
) 
WHERE rnum >= 1000001 

Execution Time: 0.2 seconds. 

Results: 
2134696, 
2134697, 
2134692, 
2134693, 
2134694, 
2134695, 
2134698, 
2134699, 
2134700, 
2134701 

SELECT * 
FROM mytable 
WHERE ID IN (
    2134696, 
    2134697, 
    2134692, 
    2134693, 
    2134694, 
    2134695, 
    2134698, 
    2134699, 
    2134700, 
    2134701 
) 

Execution Time: 0.03 seconds. 

最初のクエリは、一緒に他の2のように高速である必要がありますが、それははるかに遅いです。

これはなぜ誰かが説明し、より良い解決策を提案できますか?

答えて

2

最初に、2つのテーブル(またはインデックス)スキャン(数百万行のスキャン)を行い、それらを結合して行をフィルタリングしています。

2番目と3番目のクエリでは、それぞれ1つのテーブル(またはインデックス)スキャンが実行されていますが、それらは一緒に結合されていません。単一のテーブルスキャンを行い

SELECT * 
FROM (
    SELECT r.*, ROWNUM rnum 
    FROM (
     SELECT * 
     FROM mytable 
     ORDER BY ID 
    ) r 
    WHERE ROWNUM <= 1000010 
) 
WHERE rnum >= 1000001 

次のようなものを使用する必要があります。

Oracle 12cでは、使用することができます:総レコードはカウントして、レコード取得のための

SELECT * 
FROM  MYTABLE 
ORDER BY id 
OFFSET 1000000 ROWS FETCH NEXT 10 ROWS ONLY 
+0

おかげ

変化。私はあなたの質問から始めましたが、結果を返すのに30秒以上かかることもありました。現在のところ、私の解決策のための最も速い方法は、最初にIDのリストを取得し、関連するデータを取得するために別のクエリを起動することです。私には夢中だが、うまくいく。私はOracle 12がこれをよりうまく処理すると仮定します。 – markvpc

+0

@markvpc 'ID'列にインデックスがありますか? – MT0

+0

はい、それはプライマリキーの列であり、それ自身でフェッチするのは非常に高速です。この問題は、そのテーブル内の他のデータを取得するときに発生します。 – markvpc

0

最善の方法を。 【YOURTABLENAME] 変化2及び100(2 "PAGENO"、100 "PERPAGE")応答を

with 
XPARAMS as (select 2 "PAGENO", 100 "PERPAGE" from dual) 
,P2 as (select (XPARAMS.PAGENO-1)*XPARAMS.PERPAGE "STARTNO", XPARAMS.PAGENO*XPARAMS.PERPAGE "ENDNO" from XPARAMS) 
,D1 as (select * from [YOURTABLENAME] t order by ID) 
,DCOUNT as (select count(*) "TOTALCOUNT" from D1) 
,D2 as (select rownum "RN" , D1.* from D1) 
,D3 as (select D2.* from D2,P2 where D2.RN between P2.STARTNO and p2.ENDNO) 
select D3.RN, DCOUNT.TOTALCOUNT, XPARAMS.PAGENO, XPARAMS.PERPAGE, D3.* from D3,DCOUNT, XPARAMS 
関連する問題