
Oracle SQLチューニング(第41回)「ROWNUMの理解と関連SQL性能問題の理解」(1/6回)
今回から6回シリーズで、「ROWNUMの理解と関連SQL性能問題の理解」と題して、情報をお届けします。それでは、早速始めましょう。
ROWNUMはOracleで提供する仮想カラムで、Select節で使う場合には抽出するデータの順番を付与する用途で使われ、Where節に使う場合には抽出するデータのうち一部データだけ持ってくる用途で使われます。 特にWhere節に使われるROWNUMはインデックスの特性を利用して、部分範囲処理に誘導でき、うまく使えば効率的なSQLになります。
ROWNUMが1回の順番を付与することと、SQLを解釈するときにROWNUMの使用位置とSQLのコンポーネントとの関係を理解すれば、ROWNUMをより効率的に使用することができるでしょう。
これから、基本的なROWNUMに対する内容を調べていきましょう。
12.1 ROWNUMデータを先に抽出した後、問い合わせよう
ROWNUM_T1テーブルには下記のように合計10件のデータがあります。
10件のデータに対して下記のようにSQLを実行してみましょう。
テーブル12-1. ROWNUMのデータ抽出
SQL[1] |
SQL[2] |
||
SELECT * |
C1 C2 C3 |
SELECT * |
no rows selected |
SQL[1]とSQL[2]はそれぞれの条件に合うデータが抽出されなければならないと予想されました。 しかしSQL[1]は1 ~ 5まで合計5件のデータが抽出されましたが、SQL[2]は何のデータも抽出されませんでした。
このような結果が導き出された理由は何なのでしょうか?
解答はROWNUMの特性で探してみることで得ることができます。 ROWNUMはSQL結果セットに順番を付与する仮想カラムで、Fetch段階で抽出する最初の行に1を付与します。 そして次の行が抽出されるたびにROWNUMの値を次々と増加させます。 ところで1が存在しないならば、次の順番を付与できないので何のデータも抽出されません。
すなわち、ROWNUMを利用して、ただ一件(ROWNUM=1)のデータだけ抽出したり、1から始めて順にN件のデータを抽出するのは可能ですが、ROWNUMの開始を1でない値から抽出しようとする場合にはデータが抽出されません。
ROWNUMの使用を誤った事例
WHERE ROWNUM = N ( N > 1 )
WHERE ROWNUM > N ( N > 1 )
それならSQL[2]が本来の作成意図のとおりデータを抽出できる方法はないのでしょうか?
ROWNUMが6 ~ 10のデータ(C1値が6 ~ 10)を抽出するためには、次のSQLのように先に抽出対象データにROWNUMを1から順番を付けた後ROWNUMが6 ~ 10までのデータを抽出すれば良いのです。
いかがでしたでしょうか?次回は、「ORDER BYとROWNUMを同じ位置に置くのをやめよう」という内容でお送りします。ご期待ください。では、See You ^^