2

ビューとして保存したいクエリがあります。

WITH subquery AS ( SELECT aaa_id, ... FROM table_aaa ... )
SELECT subquery.aaa_id, ... FROM table_bbb JOIN subquery USING ( ... )
;

[注: 実際には、私のクエリはこれよりもはるかに複雑で、いくつかWITHのサブクエリがあり、多くが実行JOINSされ、すべてJOIN一緒に編集されています。しかし、問題を解決するために使用できる一般的なガイダンスを探しています。]

このクエリの実行には、全テーブル スキャンが含まれます。WHERE句には基準が含まれていないため、これは理にかなっています。ただし、次のような句を含めることで、テーブル全体のスキャンのほとんどを排除できます。

WITH subquery AS ( SELECT aaa_id, ... FROM table_aaa ... WHERE aaa_id = :id)
SELECT subquery.aaa_id, ... FROM table_bbb JOIN subquery USING ( ... )
;

WHEREただし、ビューを作成するときに条件を適切な場所に配置するオプションがないようです。

CREATE OR REPLACE VIEW vw_my_view AS
WITH subquery AS ( SELECT aaa_id, ... FROM table_aaa ... )
SELECT subquery.aaa_id, ... FROM table_bbb JOIN subquery USING ( ... )
;

SELECT ... FROM vw_my_view WHERE aaa_id = :id
;

この場合、実行計画にはまだ全表スキャンが含まれています。WHERE句が実際にサブクエリに挿入できることを示唆する方法はありWITHますか?

4

2 に答える 2

2

私は似たような経験があり、一般的な解決策はありませんが、次のことをお勧めします。

  • 「SELECT * FROM v$parameter2;」を実行します。_complex_view_merging がオンになっていることを確認してください。初期の 10g リリースの 1 つに関連する厄介なバグがあったため、一部のデータベース管理者はそれをオフにし、修正後に再びオンにするのを忘れた可能性があります。

  • ヒントに関するすべての考慮事項は、最後の手段として残してください。私の経験では、オプティマイザーはすでにそれらを回避するためにできる限りのことを行っているため、完全なテーブル スキャンを防ぐためにそれらが役立つことはめったにありません。

  • 主キーが最終的にビューをフィルタリングするものであるベーステーブルがある場合は、ビューのメインクエリがそれで始まり、複雑な with 句クエリに結合するように設定してみてください。結合は完全に冗長です(つまり、オラクルが複雑なビットに結合する前に、そのベース テーブルで簡単なフィルタリングを行う機会を与えます)。ビューがフィルター処理される列が、complex_query ではなく、そのベース テーブルから直接選択されていることを確認してください。だから何か

.

     with (complicated_query)
     select base_table.key1, complicated_query.*
     from base_table
     join complicated_query on base_table.key1 = complicated_query.key1;
  • 非相関サブクエリを使用するフィルターがある場合は、それらを相関サブクエリに切り替えてみてください (逆も同様です)。

  • 論理的には結果に違いがなくても、結合ステートメントの順序や FROM 句で開始するテーブルをいじってみてください。これは少し絶望的な賭けですが、これを行うことで実行計画が確実に改善されました。Oracle クエリの最適化は、必ずしも合理的なプロセスではありません。

于 2013-02-13T22:32:57.397 に答える
0

ここで説明されているように、コンテキスト パラメータを 使用でき ます vs- URL が再度変更された場合に備えて、where 条件付きのビュー)

このようにして、ビュー定義の奥深くに WHERE aaa_id = SYS_CONTEXT ('my_namespace', 'aaa_id') を配置し、次のように使用できます。

CREATE OR REPLACE VIEW vw_my_view AS
WITH subquery AS ( SELECT aaa_id, ... FROM table_aaa ...
   WHERE aaa_id = SYS_CONTEXT ('my_namespace', 'aaa_id'))
SELECT subquery.aaa_id, ... FROM table_bbb JOIN subquery USING ( ... )
;

DBMS_SESSION.SET_CONTEXT('my_namespace', 'aaa_id', TO_CHAR(:id));
SELECT ... FROM vw_my_view  /* this is not needed any more: WHERE aaa_id = :id */

より多くの例と説明については、Google (検索用語「paramet(e)rized view in oracle」) ...

于 2013-10-19T18:48:08.627 に答える