嵌套数据库视图可以吗?

时间:2009-09-29 20:27:53

标签: sql oracle plsql views

在甲骨文的世界里,我的印象是基于其他观点的观点被认为是不好的做法。当我试图解决性能问题和嵌套看起来过度并隐藏在底层视图中不必要的复杂性时,我自己就抱怨过这个问题。现在我发现自己处于这样的状态:它可能不那么明确:

我的用户非常特别需要从一个视图中获取会计编号,以匹配对其进行进一步处理的会计编号。如果他们改变任何一个,他们希望对方立即反映,没有任何人在几年内不必考虑这个要求,报告显示不匹配的数字,而他们想出的东西。

在这种情况下嵌套视图是否可以?

如果内部视图包含一个包含相关价格的进一步重要视图(即您在确定价格时“始终”应该使用此视图),它会改变吗?

10 个答案:

答案 0 :(得分:6)

嵌套视图的主要问题是查询优化器更容易混淆并产生次优计划。除此之外,在视图上使用视图没有特定的开销,除非他们做了一些优化器无法将谓词推入的内容。

这意味着最好的选择是尝试嵌套视图。看看你是否从报告中获得了合理的查询计划。如果确实会导致问题,那么您可能需要重新考虑自己的策略。

答案 1 :(得分:5)

我将从最佳实践的角度回答:

我只会暂停几次使用Views on Views。

  1. 嵌套似乎已经失控......比如超过3级。我嵌套的原因是为了使代码更容易维护。一旦我开始达到这一点,它开始感觉有点太复杂,无法理解。

  2. 嵌套使用分析函数的视图。出于某种原因,我个人在使用分析功能嵌套视图方面没有很好的经验。

  3. 嵌套按性质进行完整扫描的视图。虽然我认为查询优化器可能足够智能来处理这个问题,但当我查看视图的逻辑时,我看起来就错了。

  4. 表现是一个很大的问题。这并不是说优化器可能会出错,但这就是说在我发布它之前,我将测试它以确定我是否能够更快地找到它。

  5. 除此之外,我已经非常成功地使用了对视图的观点。

答案 2 :(得分:3)

我认为你在这里滑坡,代码重用和性能将发生冲突。你可以尝试一下,看看它对性能的影响有多严重。我们在这里有几个数据库,他们在视图之上堆叠了视图,坦率地说,性能很糟糕,现在每个人都希望他们没有那样设计。

答案 3 :(得分:2)

在编码时间,代码的简易性或质量与性能之间总是需要权衡。

嵌套视图非常容易编码,并且在适当的情况下,使其易于阅读。它还可以减少时间。它可以说会降低质量并且通常会降低性能......但是会降低多少?

这都是主观的。如果它有意义,请滚动它。不要过早地优化代码。

答案 4 :(得分:1)

最佳做法并不总能涵盖所有内容。我认为你有一个明确的理由来嵌套它们,就这一次。

答案 5 :(得分:1)

我在Oracle 10g R2中嵌套了3层深度的视图。性能似乎与视图中的select语句相关,而不是视图深度。特别是“IN”条款似乎造成了很多麻烦。

答案 6 :(得分:0)

在构建复杂数据库查询的过程中注意也是一件好事,有时嵌套视图是最好的 - 例如,如果你需要在2列上构建​​任何数学运算符,例如SUM(Col1,Col2)它可以更好地嵌套视图,以便总和本身就是一列而不必像

那样做

“SELECT Total / SUM(Col1,Col2),SUM(Col1,Col2)* 2,Col1 / SUM(Col1,Col2)......”

但是我不确定我是否理解100% - 为什么需要2次观看?两个用户都不能查看1视图,并且可以在视图中的另一层中导出进一步处理吗?

答案 7 :(得分:0)

使用视图的最佳理由是:

  1. 防止重复相同的查询。
  2. 阻止其他查询编写者直接访问表
  3. 创建一层安全性(类似于#2)。
  4. 我确实意识到它也可以帮助简化更复杂的查询,但您可以使用它。您可能会发现用户定义的函数(表)可能是更好的解决方案。无论哪种方式,性能都会受到影响。

答案 8 :(得分:0)

嵌套视图有意义。请注意,不要让它们过于笼统。


我确实看到一个系统有一个视图,其中有14个表明确提到,其中一些与外部自连接有关,而一些“表”本身就是视图。我不喜欢它,但是DBMS对它的处理非常好(鉴于它已经回到了80年代后期)。很多架构都是由数据建模工具生成的。

CREATE VIEW IBB_V_Project AS
    SELECT  A.Project_Iref,
            A.Section_Iref,
            B.Section_Eref,
            N.Company_Iref,
            N.Company_Name,
            A.Product_Desc,
            A.Project_Type_Iref,
            D.Project_Type,
            A.Person_Iref,
            F.Full_Name,
            A.Respon_Iref,
            G.Post_Location,
            A.Project_Stat_Iref,
            E.Project_Status,
            A.Source_Iref,
            I.Source,
            A.Sic_Iref,
            L.Sic_Eref,
            A.Op_Activity_Iref,
            M.Op_Activity_Desc,
            A.Involve_Iref,
            K.IBB_Involvement,
            A.Nature_Iref,
            C.Nature_Of_Next_Act,
            A.Internat_Mobile,
            A.Whether_Cop_Case,
            A.Closed_Ind,
            A.Next_Action_Date,
            A.Creation_Date,
            A.Last_Edit_Date,
            A.Last_Editor_Iref,
            H.Logname

    FROM    IBB_Project A,
            IBB_Section B,
            IBB_R_Proj_Type D,
            IBB_R_Project_Stat E,
            IBB_Personnel H,
            OUTER IBB_R_Next_Act C,
            OUTER IBB_Personnel F,
            OUTER (IBB_Post_Respon X, OUTER IBB_V_Post_Resp2 G),
            OUTER IBB_R_Source I,
            OUTER IBB_R_Involvement K,
            OUTER IBB_Sic L,
            OUTER IBB_Op_Act M,
            OUTER IBB_V_Proj_Co2 N

    WHERE   A.Section_Iref      = B.Section_Iref
      AND   A.Project_Type_Iref = D.Project_Type_Iref
      AND   A.Project_Stat_Iref = E.Project_Stat_Iref
      AND   A.Last_Editor_Iref  = H.Person_Iref
      AND   A.Nature_Iref       = C.Nature_Iref
      AND   A.Person_Iref       = F.Person_Iref
      AND   A.Respon_Iref       = X.Respon_Iref
      AND   X.Respon_Iref       = G.Person_Iref
      AND   A.Source_Iref       = I.Source_Iref
      AND   A.Sic_Iref          = L.Sic_Iref
      AND   A.Op_Activity_Iref  = M.Op_Activity_Iref
      AND   A.Project_Iref      = N.Project_Iref
      AND   A.Involve_Iref      = K.Involve_Iref;

外连接表示法特定于Informix(现在也支持SQL标准表示法)。

请注意,IBB_V_Post_Resp2和IBB_V_Proj_Co2都是自己的视图。 实际上,IBB_V_Proj_Co2是一个3表视图,确切的细节未知但是 形式:

CREATE VIEW IBB_V_Proj_Co2 AS
    SELECT  A.Project_Iref,
            A.Some_Other_Col col01,
            B.Xxxx_Iref,
            B.Some_Other_Col col02,
            C.Yyyy_Iref,
            C.Some_Other_Col col03
    FROM    IBB_Project A,
            OUTER (IBB_R_Xxxx B, IBB_R_Yyyy C)
    WHERE   A.Xxxx_Iref = B.Xxxx_IrEf
      AND   B.Yyyy_Iref = C.Yyyy_Iref;

这意味着IBB_V_Project视图具有外部自联接 IBB_Project。 IBB_V_Post_Resp2视图可能涉及3个表 (我的注释有点不清楚,早在1993年,当我记录这些信息时)。

CREATE VIEW IBB_V_Post_Resp2 AS
    SELECT  A.Person_Iref,
            A.Some_Other_Col col01,
            B.Xxxx_Iref,
            B.Some_Other_Col col02,
            C.Yyyy_Iref,
            C.Some_Other_Col col03
    FROM    IBB_Personnel A,
            IBB_R_Xxxx B,
            IBB_R_Yyyy C
    WHERE   A.Xxxx_Iref = B.Xxxx_Iref
      AND   B.Yyyy_Iref = C.Yyyy_Iref;

Zzzz_Iref列是SERIAL或INTEGER外键 引用SERIAL键。

主视图定义引用14个表,包含4个内部联接和9个 外连接。当考虑交叉引用的视图时,那里 共有18个表,有7个内连接和10个外连接。

答案 9 :(得分:0)

真的不想陷入整个嵌套视图的事情

想一想这个想法......你试图加入一个表来找不匹配...我会使用Oracle函数'减去'.... MINUS从第一个表中选择元素然后删除第二个SELECT语句也返回的行。

SELECT num   FROM(SELECT 1 AS num           来自双重      UNION ALL         SELECT 2 AS num           来自双重      UNION ALL         SELECT 3 AS num           FROM DUAL)base_view

MINUS

SELECT 2 AS num   来自双重