17

OracleSTART WITH ... CONNECT BY句は、同じクエリで条件を適用する前に適用されます。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 BYandWHERE句に関して同様のパフォーマンス最適化を行いましたか? クエリ B がクエリ A よりもはるかに優れていることをどのように説明しますか?

4

4 に答える 4

17

クエリ A は、営業部門のマネージャーから始めて、すべての従業員を取得することを示しています。オラクルは、クエリで返されるすべての従業員が営業部門にいることを「認識」していないため、その情報を使用して、CONNECT BY を実行する前に処理するデータのセットを減らすことができません。

問合せ Bは、処理するデータのセットをセールスの従業員だけに明示的に減らします。これにより、Oracle は CONNECT BY を実行する前にこれを行うことができます。

于 2009-07-04T10:04:23.263 に答える
7

これにより、究極のパフォーマンスが得られるはずです。

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最適化が機能するには、インデックスと両方の条件の両方が必要であることに注意してください。

于 2011-12-27T09:25:29.157 に答える
2

これは同様のクエリですが、簡単に言えば、以前のオプションによる二重接続よりもネストされた 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を使用してフィルタリングすることです。

于 2013-12-03T21:24:42.217 に答える
1

従業員の指標は何ですか?従業員 ID にインデックスを作成することをお勧めします。また、employeeid を主キーとして宣言した結果として、1 つある可能性があります。

managerid のインデックスを使用すると、パフォーマンスが向上する場合もあります。それを試してみてください。これは、新しい従業員を挿入したり、管理関係を再編成したりするときに、パフォーマンスの低下とバランスを取る必要があります。

于 2009-07-04T11:39:15.070 に答える