2023.01.11
SQLチューニング(第42回)「ROWNUMの理解と関連SQL性能問題の理解」(2/6回)
今回は、「ROWNUMの理解と関連SQL性能問題の理解」の2回目です。それでは、始めましょう。
12.2 ORDER BYとROWNUMを同じ位置に置くのをやめよう
SQLチューニングをしていれば、ROWNUMとOrder By節を同じ位置に使って誤ったデータが抽出されるのを時々目撃することになります。
間違って抽出されたデータが照会目的だけで使われるならばまだ幸いですが、このデータが違うトランザクションのために抽出された場合、データの整合性まで毀損され大きい問題になります。 このような問題を予防するためにはROWNUM条件がSQLの構成要素らと一緒に使われる時どんな順序で実行されるのかから理解する必要があります。
SQL構成要素は以下のような順序で実行されます。
- FROM,WHERE節を処理
- ROWNUM組にしても適用
- SELECT COLUMN LIST節を適用
- GROUP BY節を適用
- HAVING節を適用
- ORDER BY節を適用
すなわち、Order By節がROWNUM条件と同じ位置にあるならば、ROWNUM条件を先に処理した後Order By節が実行されるということが分かります。 したがってOrder By節でデータを整列した後ROWNUMでいくつかのデータだけ抽出しようとしましたが、整列順序に関係なく照会条件を満足するデータをROWNUMに指定した県数持ってきた後,このデータに対してだけ整列を実行するので、本来意図したこととは違ったデータを抽出することになります。
それでは例題を通じて以前調べてみた内容を確認してみましょう。
テーブル12-2. ROWNUMとORDER BY節の関係
SQL[1] | SQL[2] | ||
SELECT * FROM ( SELECT c1, ROWNUM AS rnum FROM t1 ORDER BY c1 DESC ) WHERE ROWNUM <= 5; | C1 RNUM —— —— 10000 10000 10000 20000 9999 9999 9999 19999 9998 9998 | SELECT c1, ROWNUM AS rnum FROM t1 WHERE ROWNUM <= 5 ORDER BY c1 DESC ; | C1 RNUM —— —— 5 5 4 4 3 3 2 2 1 1 |
SQL[1]は全体データでOrder Byを実行後ROWNUMを処理した結果で、SQL[2]はOrder By節とROWNUMを同じ位置で実行した結果です。 テーブル12-2で二つの結果値を確認してみると、ROWNUM条件を使った位置により、互いに全く違う結果値が抽出されるのを確認することができます。 したがって整列したデータのうち一部いくつかの行を問い合わせたいならOrder By節を先に処理した後、これでインライン ビューで作って、ROWNUM処理を実行することで、意図したデータを抽出することができます。
「ROWNUMの理解と関連SQL性能問題の理解」の第2回目は、以下でしたでしょうか?次回は、「ROWNUM=1は、ROWNUM<=1で使おう」と題して、お送りします。ご期待ください。では、See You ^^