可以使用VIEW进行SELECT操作来提高性能吗?

时间:2009-02-26 14:02:32

标签: sql performance oracle

致力于提高决策中心的绩效,我们确定的瓶颈之一是数据库。

所以我想知道,oracle是否为其视图编制了执行计划?

假设假设我在请求期间使用了10000次定义的查询。 查询类似于:

select A, B, C 
from aTbl, bTbl left join cTbl on bTbl.cTblID = cTbl.objectkey
where aTbl.objectkey = bTbl.parentkey

在代码中,我想使用其他过滤参数获取上述查询的结果,例如:WHERE aTbl.flag1 = <<NUMBER>>

现在我有两个选择:

  1. 使用上述SQL创建预准备语句,然后重用该对象。
  2. 将上述select (aTbl, bTbl, cTbl)放入VIEW,然后在此视图上创建预备语句,从而有利于预编译的Oracle执行计划。
  3. 你会建议什么?

6 个答案:

答案 0 :(得分:6)

Oracle 可以将谓词推送到视图中,如果它认为它会改进计划。

如果您想避免这种情况,可以使用以下任一方法:

  1. 在视图定义中添加/*+ NO_MERGE *//*+ NO_PUSH_PRED */提示
  2. 在使用该视图的查询中添加/*+ NO_MERGE (view) *//*+ NO_PUSH_PRED (view) */提示。
  3. 如果您想强制执行此操作,请使用他们的couterparts /*+ PUSH_PRED *//*+ MERGE */

    只要涉及性能,使用已定义的视图(如果它当然不是MATERIALIZED VIEW)或内联视图(即子查询)之间没有区别。

    Oracle编译的计划不是针对观看,而是针对精确的SQL文本。

    即,以下陈述:

    SELECT A, B, C 
    FROM   aTbl, bTbl
    LEFT JOIN cTbl ON 
      bTbl.cTblID = cTbl.objectkey
    WHERE aTbl.objectkey = bTbl.parentkey
      AND aTbl.flag1 = :NUMBER
    
    SELECT *
    FROM
      (
      SELECT A, B, C, flag1
      FROM   aTbl, bTbl
      LEFT JOIN cTbl ON 
        bTbl.cTblID = cTbl.objectkey
      WHERE aTbl.objectkey = bTbl.parentkey
      )
    WHERE flag1 = :NUMBER
    
    /*
    CREATE VIEW v_abc AS
    SELECT A, B, C, flag1 
    FROM   aTbl, bTbl
    LEFT JOIN cTbl ON 
      bTbl.cTblID = cTbl.objectkey
    WHERE aTbl.objectkey = bTbl.parentkey
    */
    
    SELECT A, B, C
    FROM v_abc
    WHERE flag1 = :NUMBER
    
    该计划将:

    1. 是相同的(如果Oracle将选择推送谓词,这很可能);
      • 首次调用时编译;
      • 再次打电话时重复使用。

答案 1 :(得分:2)

视图并不是你想要的。

您要做的是使用bind variables作为您的旗帜条件;这样你就可以编译一次语句,并为不同的标志执行多次。

就像风格一样 - 您应该决定如何指定联接,并继续使用,以保持一致性和可读性。原样,你有atbl和btbl的显式连接条件,而btbl和ctbl的“左连接”语法在事物的方案中并不重要,但看起来和读起来有点奇怪。

祝你好运!

答案 2 :(得分:2)

视图不会导致性能提升。有时它们可​​能会降低性能。我不是说你应该避免观点;在使用之前了解可能的影响。 Oracle documentation说:

  

视图可以加速并简化应用程序设计。简单的视图定义可以掩盖数据模型的复杂性,这些复杂性来自程序员,其优先级是检索,显示,收集和存储数据。

     

但是,虽然视图提供了干净的编程接口,但它们可能会导致次优的资源密集型查询。最糟糕的视图使用类型是视图引用其他视图以及它们在查询中连接时的情况。在许多情况下,开发人员可以直接从表中满足查询而无需使用视图。通常,由于视图的固有属性,视图使优化器难以生成最佳执行计划。

答案 3 :(得分:1)

我认为这不是你要找的东西,但如果说谎的桌子不经常改变,比如每天或每小时,你可以使用物化视图。这基本上是存储的结果集。您还可以在它们上添加索引。它们可以按计划刷新,也可以在下表中更改(不是真正用于OLTP)。

Here is Oracle's docs on using materialized views.

答案 4 :(得分:0)

Oracle中没有“预编译”视图:从定义视图中进行选择与直接从表中选择(假设所有连接和条件相同)没有不同的性能。

当您说您的查询“在请求期间被使用了10000次”时,我感到很困惑。这听起来不是最佳的 - 为什么会这样?

答案 5 :(得分:0)

这里的答案是肯定的,没有。

oracle只会解析一次语句。关键是它必须是“相同的”而不仅仅是相似的。这包括间距(或制表符)和注释。

使用create view创建视图允许您按原样修复语句并允许重复使用。

然而

SELECT * FROM VIEW

SELECT * FROM VIEW WHERE A=1

是两个不同的陈述/查询。

要获得最大的语句重用,您必须使用绑定变量,而不仅仅是将条件连接到SELECT上。而且通常意味着准备好的陈述

如果可以的话,你还没有提到哪种主语言我会用特定的例子更新,如果可以的话。

PL / SQL中的

DECLARE
  cursor c (cpflag aTbl.flag1%TYPE )is
   select A, B, C 
     from aTbl, bTbl, cTbl
    where aTbl.objectkey = bTbl.parentkey
      and bTbl.cTblID = cTbl.objectkey
      and aTbl.flag1 = cp_flag ;

vtype c%rowtype;
BEGIN

open c(100);
fetch c into vtype;
close c;

open c(200);
fetch c into vtype;
close c;
END;

在诸如java之类的东西准备你放“?”的语句作为placholders并使用stmt.bind()调用

希望有所帮助