1

Oracle 9iに自己参照テーブルがあり、そこからデータを取得するビューがあります。

CREATE OR REPLACE VIEW config AS
SELECT c.node_id,
       c.parent_node_id,
       c.config_key,
       c.config_value,
       (SELECT c2.config_key 
          FROM vera.config_tab c2 
         WHERE c2.node_id = c.parent_node_id) AS parent_config_key,
       sys_connect_by_path(config_key, '.') path,
       sys_connect_by_path(config_key, '->') php_notation
  FROM config_tab c
CONNECT BY c.parent_node_id = PRIOR c.node_id
 START WITH c.parent_node_id IS NULL
 ORDER BY LEVEL DESC

このテーブルには、PHPアプリケーションの構成が格納されています。ここで、Oracleビューで同じ構成を使用する必要があります。

パスごとにビューからいくつかの値を選択したいのですが、残念ながらこれには0.15秒かかるため、許容できないコストになります。

SELECT * FROM some_table
 WHERE some_column IN (
   SELECT config_value FROM config_tab WHERE path = 'a.path.to.config'
 )

最初はsys_connect_by_pathの関数インデックスを考えましたが、CONNECT BY句も必要なため、不可能です。

'config'ビューからパス列のインデックスをエミュレートするにはどうすればよいですか?

4

1 に答える 1

2

でデータが頻繁に変更されない場合は、ビューと同じクエリでマテリアライズドビューconfig_tabを使用できます。次に、マテリアライズド・ビューの列に索引を付けることができます。path

CREATE MATERIALIZED VIEW config
   REFRESH COMPLETE ON DEMAND 
   AS <your_query>;

CREATE INDEX ix_config_path ON config (path);

これは複雑なクエリであるため、MV内のデータが古くならないように、ベーステーブルが更新されるたびにマテリアライズドビューを完全に更新する必要があります。

アップデート

  • pathはとして定義されますVARCHAR2(4000)。インデックスを作成するために、この列のサイズを制限できます。sys_connect_by_path(...)クエリで、SUBSTR(sys_connect_by_path(..., 1, 1000)たとえばに置き換えます。
  • 複雑なMVでREFRESHONCOMMITを使用することはできません。単純なトリガーは機能しません。ベーステーブルを更新するコードを変更して、なんらかの方法で更新を含める必要があります。これがご使用の環境で実用的かどうかはわかりません。
  • MVを更新するジョブを送信するトリガーを使用することもできます。コミットするとジョブが実行されます(これはの機能ですdbms_job)。これは、トランザクションごとに1回だけジョブをトリガーすることを確認する必要があるため(たとえば、パッケージ変数を使用して)、より複雑になります。繰り返しますが、これはベーステーブルを頻繁に更新しない場合にのみ実用的です。
于 2010-03-09T14:48:54.703 に答える