Oracle 無 LIMIT/OFFSET 語法 (12c 前),分頁依賴 ROWNUM 偽欄位。本文詳細比較兩種寫法效能差異,解釋 CBO 謂詞下推機制,並給出生產環境建議範本。
SELECT * FROM (
SELECT a.*, ROWNUM rn
FROM (SELECT * FROM your_table WHERE conditions ORDER BY sort_col) a
WHERE ROWNUM <= :max_row -- 關鍵:內層限制上限
)
WHERE rn >= :min_row; -- 外層過濾下限
參數範例:第 3 頁、每頁 20 筆 → :max_row = 60, :min_row = 41。
ROWNUM <= :max_row **下推** 至最內層查詢。rn >= :min_row 僅在少量結果集上過濾,成本極低。SELECT * FROM (
SELECT a.*, ROWNUM rn
FROM (SELECT * FROM your_table WHERE conditions ORDER BY sort_col) a
)
WHERE rn BETWEEN :min_row AND :max_row; -- 無法下推,內層必須產生所有符合條件的行
/*+ FIRST_ROWS(100) USE_NL(t2) LEADING(t1) */ 強制 NL 並指定驅動表。SELECT * FROM your_table
WHERE conditions
ORDER BY sort_col
OFFSET 40 ROWS FETCH NEXT 20 ROWS ONLY;
內部仍轉換為 ROWNUM 邏輯,但語法更直觀、可攜性佳 (ANSI SQL:2008)。
ORDER BY sort_col, pk_col。:max_row, :min_row 避免硬解析,利用游標共用。/*+ FIRST_ROWS(n) */ Hint 引導優化器選擇 NL + 索引路徑。V$SQL_WORKAREA_ACTIVE 確認無大量單次排序溢寫磁碟。