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 子句。

任何建议如何从“配置”视图模拟路径列上的索引?

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 上使用 REFRESH ON COMMIT。一个简单的触发器是行不通的。您将不得不修改更新基表的代码以以某种方式包含刷新,我不知道这在您的环境中是否实用。
  • 您还可以使用触发器来提交将刷新 MV 的作业。一旦您提交,该作业将执行(这是 的一个功能dbms_job)。这更复杂,因为您必须检查每个事务只触发一次作业(例如使用包变量)。同样,这仅在您不经常更新基表时才实用。
于 2010-03-09T14:48:54.703 回答