Oracle START WITH ... CONNECT BY
句が適用されますbefore同じクエリでWHERE
条件を適用します。したがって、WHERE制約はCONNECT BY
の最適化に役立ちません。
たとえば、次のクエリは、フルテーブルスキャンを実行する可能性があります(dept_id
の選択性は無視されます)。
SELECT * FROM employees
WHERE dept_id = 'SALE'
START WITH manager_id is null
CONNECT BY PRIOR employee_id = manager_id
私は2つの方法でパフォーマンスを改善しようとしました:
クエリA:
SELECT * FROM employees
START WITH manager_id is null AND dept_id = 'SALE'
CONNECT BY PRIOR employee_id = manager_id
クエリB:
SELECT * FROM (
SELECT * FROM employees
WHERE dept_id = 'SALE'
)
START WITH manager_id is null
CONNECT BY PRIOR employee_id = manager_id
両方のクエリは元のクエリよりもはるかに優れていましたが、Oracle 10gリリース2では、クエリBはAよりもはるかに優れていました。
CONNECT BY
句とWHERE
句に関して扱う同様のパフォーマンス最適化はありましたか?クエリBはクエリAよりもはるかに優れていることをどのように説明しますか?
クエリAは、営業部門のマネージャーから始めて、すべての従業員を取得すると述べています。 allクエリが返される従業員が営業部門に所属することをOracleが認識していないため、その情報を使用して、CONNECTを実行する前に処理するデータセットを削減することはできません。沿って。
クエリB explicitly作業するデータのセットをSalesの従業員だけに減らし、OracleはCONNECT BYを実行する前にこれを行うことができます。
これにより、究極のパフォーマンスが得られます。
CREATE INDEX i_employees_employee_manager_dept ON employees (employee_id,manager_id,dept_id);
CREATE INDEX i_employees_manager_employee_dept ON employees (manager_id,employee_id,dept_id);
SELECT * FROM employees
START WITH manager_id is null AND dept_id = 'SALE'
CONNECT BY PRIOR employee_id = manager_id AND dept_id = 'SALE'
最適化を機能させるには、インデックスとAND
の両方の条件が必要であることに注意してください。
これは似たようなクエリですが、簡単に言えば、ネストされたSQLを使用すると、以前のオプションによる二重接続よりも速く機能しました。
'SELECT level, XMLElement("elemento", XMLAttributes(codigo_funcion as "Codigo",
nombre_funcion as "Nombre",
objetivos as "Objetivos",
descripcion as "Descripción",
''rightHanging'' as "layout"))
FROM (
SELECT * FROM dithe_codigo_funcion
WHERE nodo_raiz = ''PEP''
)
START WITH codigo_funcion = ''PEP''
CONNECT BY PRIOR codigo_funcion = nivel_anterior';
したがって、専門知識があまりない私の推奨は、ネストされたSQLを使用してフィルタリングすることです。
従業員のインデックスは何ですか?あなたはemployeeidのインデックスを持っている方がいいです。また、employeeidを主キーとして宣言した結果として1つある可能性があります。
Manageridのインデックスでもパフォーマンスが向上する場合があります。それを試してみてください。これは、新しい従業員を挿入するとき、または管理関係を再編成するときに、パフォーマンスの低下とバランスを取る必要があります。