我有一些用户非常需要一个视图的会计数字与另一个视图进行匹配,后者对它们进行进一步处理。如果他们在其中一个视图中做出任何更改,他们希望另一个视图立即反映出来,而无需在几年后考虑此要求,同时显示不匹配的数字并找出问题。
在这种情况下嵌套视图是否可以接受?
如果内部视图包含一个重要的视图,其中包含相关价格(即在确定价格时“总是”应该使用此视图),这是否会改变事情?
嵌套视图的主要问题在于查询优化器更容易混淆并产生次优计划。除此之外,使用视图嵌套没有特定的开销,除非它们执行某些优化器无法将谓词下推到的操作。
这意味着最好的选择是尝试使用嵌套视图。查看报告是否能得到合理的查询计划。如果出现问题,则可能需要重新考虑您的策略。
从最佳实践的角度来看,我会这样回答:
只有在以下几种情况下,我才会考虑使用 Views on Views。
嵌套似乎已经失控...超过 3 层深度。我嵌套的原因是为了使代码更易于维护。一旦我开始达到这个点,它就开始感觉有点太复杂,难以理解。
嵌套一个使用分析函数的视图。出于某种原因,我个人对嵌套带有分析函数的视图没有很好的体验。
嵌套视图本质上进行全表扫描。虽然我认为查询优化器可能足够聪明,能够处理这个问题,但当我审查视图的逻辑时,它看起来就不对劲。
性能是一个非常重要的问题。这并不是说优化器可能会出错,而是在发布之前,我会测试它,看看是否能找到更快的方法来完成它。
除此之外,我已经成功地使用了 Views on Views。
我觉得你现在正处于代码重用和性能冲突的滑坡上。你可以尝试一下,看看它会对性能产生多大的影响。我们这里有几个数据库,它们在视图之上堆叠了视图,说实话性能很糟糕,现在所有相关人员都希望他们当初没有那样设计。
在编码时间、代码的易读性和质量以及性能之间总是存在一种权衡。
嵌套视图很容易编写,并在合适的情况下使代码易于阅读。它也可以减少时间。这可以说降低了代码质量,而且经常会降低性能...但降低了多少?
这都是主观的。如果有意义,请继续使用。不要过早地优化您的代码。
我在Oracle 10g R2中嵌套了3层视图。性能似乎与视图深度无关,而与视图中的select语句有关。特别是,“IN”子句似乎引起了很多麻烦。
嵌套视图可能是有意义的。只要小心,不要让它们变得太普遍。
我曾经看到一个系统,其中一个视图明确提到了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个外连接。
在构建复杂数据库查询的过程中,有时嵌套视图是最好的选择。例如,如果您需要在两列上运算(如SUM(Col1, Col2)),则将此Sum作为一列嵌套在视图中可能比像下面这样进行处理更好:
"SELECT Total / SUM(Col1, Col2), SUM(Col1, Col2) * 2, Col1 / SUM(Col1, Col2) ..."
不过我并不确定是否完全理解——为什么需要两个视图?难道两个用户不能查看同一个视图,并在其上层的另一个视图中进行进一步处理吗?
使用视图的最好理由是:
我确实意识到它也可以帮助简化更复杂的查询,但你会习惯它。您可能会发现用户定义的函数(表格)是更好的解决方案。无论哪种方式,性能都会受到影响。
不想被纠缠在整个嵌套视图的事情上。
思考一下这个点子......你正在尝试加入一个表来查找不匹配的地方......我会使用 Oracle 函数“minus”....MINUS 从第一个表中选择元素,然后删除也由第二个 SELECT 语句返回的行。
SELECT num FROM (SELECT 1 AS num FROM DUAL UNION ALL SELECT 2 AS num FROM DUAL UNION ALL SELECT 3 AS num FROM DUAL) base_view
MINUS
SELECT 2 AS num FROM DUAL