インデックスが効かないSQL・パフォーマンスの遅いSQLとは?

インデックスが効かないSQLはパフォーマンスが遅い

インデックスが効かない原因

Oracleでパフォーマンスが遅いのにはいくつかの理由があります。

パフォーマンスが遅い理由で最も多いのが「SQLの問題」です。SQLを改善すれば、パフォーマンスがよくなって検索時間を短縮できる効果が高いです。

どういうケースがパフォーマンスが低いのか?

順番に説明します!

ちなみにデータベースの状態によってはパフォーマンスが改善されないこともあります。必ずというわけではありませんので、ザックリとした知識として覚えておくといいですね。

例1. NULL は遅い

-- nullは遅い
SELECT * FROM emp 
 WHERE empname IS NULL;

-- not nullは遅い
SELECT * FROM emp 
 WHERE empname IS NOT NULL;

ここではWHERE句の条件に「NULL」、もしくは「NOT NULL」にしています。「NULL」を使うとインデックスが使われないため、パフォーマンスが悪くなってしまいます。

例2. NOT(!=)は遅い

-- !=は遅い
SELECT * FROM emp 
 WHERE empno != 'A0001';

ここではWHERE句の条件に「!=」、つまり「NOT =」のことですね。「!=」を使うとインデックスが使われないため、パフォーマンスが悪くなってしまいます。

例3. OR は遅い

OR の遅い例

-- ORは遅い
SELECT * FROM emp 
 WHERE empno = 'A1000' OR empno = 'B1000';

ここではWHERE句で「OR」を使っています。「OR」を使うとインデックスが使われないため、パフォーマンスが悪くなってしまいます。

OR のパフォーマンス改善例

-- ORのパフォーマンス改善例
SELECT * FROM emp WHERE empno = 'A1000'
UNION ALL
SELECT * FROM emp WHERE empno = 'B1000';

「OR」で条件指定するのはやめて、「UNION ALL」で複数のSQLを結合すれば同じことができます。こちらの方が高パフォーマンスです。

例4. IN は遅い

IN の遅い例

-- INは遅い
SELECT * FROM emp 
 WHERE empno IN ('A1000','B1000');

ここではWHERE句で「IN」を使っています。「OR」と同様、「IN」を使うとインデックスが使われないため、パフォーマンスが悪くなってしまいます。

IN のパフォーマンス改善例

-- INのパフォーマンス改善例
SELECT * FROM emp WHERE empno = 'A1000'
UNION ALL
SELECT * FROM emp WHERE empno = 'B1000';

「IN」で条件指定するのはやめて、「UNION ALL」で複数のSQLを結合すれば同じことができます。こちらの方が高パフォーマンスです。

例5. 演算 は遅い

演算の遅い例

-- 演算は遅い
SELECT * FROM emp 
 WHERE score * 100 > 50;

ここではWHERE句で「score * 100」と演算しています。演算するとインデックスが使われないため、パフォーマンスが悪くなってしまいます。

演算のパフォーマンス改善例

-- 演算のパフォーマンス改善例
SELECT * FROM emp 
 WHERE score > 0.5;

演算した結果で比較すれば高パフォーマンスとなります。

例6. 複合インデックスの順番を無視 は遅い

インデックスを使用しない例

-- インデックスは{score1,score2}で作成済み
CREATE INDEX idx1 ON emp (score1 ,score2);

-- インデックスを使用しない例
SELECT * FROM emp WHERE score2 > 1;

まずインデックスが{score1,score2}で作成されていたとします。複合列でのインデックスです。この順番が重要です。

ここで 「score2」単独での検索ではインデックスがききません。インデックスは{score1,score2}であるため、「score1」か「score1,score2」はインデックスを使用しますが、「score2」はダメです。

インデックスを使用する例

-- インデックスを使用する
SELECT * FROM emp WHERE score1 > 1;

-- インデックスを使用する
SELECT * FROM emp WHERE score1 > 1 AND score2 > 5;

「score1」もしくは「score1,score2」の順番であればインデックスを使用します。

以上、Oracleでパフォーマンスが遅い理由として、インデックスを使用しないSQLを紹介しました。

コメント