需要使用sys_connect_by_path函数的索引吗?如何模仿它?

时间:2010-03-09 13:55:09

标签: oracle indexing self-reference

我在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'视图中模拟路径列上的索引?

1 个答案:

答案 0 :(得分:2)

如果您的数据在config_tab中没有经常更改,则可以使用与您的视图具有相同查询的materialized view。然后,您可以索引实体化视图的path列。

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

CREATE INDEX ix_config_path ON config (path);

由于这是一个复杂的查询,因此每次更新基表时都需要对物化视图执行full refresh,以便MV中的数据不会过时。

更新

  • 您的专栏path将被定义为VARCHAR2(4000)。您可以限制此列的大小以便对其进行索引。在您的查询中,请将sys_connect_by_path(...)替换为SUBSTR(sys_connect_by_path(..., 1, 1000),例如。
  • 您将无法在复杂的MV上使用REFRESH ON COMMIT。简单的触发器不起作用。您将不得不修改更新基表的代码以包含某种方式的刷新,我不知道这在您的环境中是否实用。
  • 您还可以使用提交将刷新MV的作业的触发器。提交后作业将执行(这是dbms_job的一项功能)。这更复杂,因为您必须检查每个事务只触发一次作业(例如使用包变量)。同样,只有在不经常更新基表的情况下,这才是实用的。