可以嵌套数据库视图吗?
在 Oracle 的世界里,我的印象是基于其他观点的观点被认为是不好的做法。当试图解决性能问题和嵌套似乎过多并且隐藏了底层视图中不必要的复杂性时,我自己也曾抱怨过这一点。现在我发现自己的想法可能不是那么明确:
我的用户非常特别需要一个视图中的会计数字来匹配另一个对它们进行进一步处理的会计数字。如果他们对其中一个进行任何更改,他们希望另一个立即反映这一点,而无需任何人在几年内考虑这一要求,并且在他们解决问题时报告显示不匹配的数字。
在这种情况下可以嵌套视图吗?
如果内部视图包含另一个包含相关价格的重要视图(即,在确定价格时“总是”应该使用此视图),它会改变事情吗?
In the world of oracle, I have the impression that views based on other views are considered to be bad practice. I myself have complained about this when the trying to solve performance issues and the nesting seemed excessive and hid away unneeded complexity in the underlying views. Now I find myself in the situation of thinking that it may not be so clear-cut:
I have users who very specifically need the accounting numbers from one view to match those of another that does further processing on them. If they ever change anything in one, they want the other to reflect that immediately, without anyone having to think of this requirement in a few years time and reports showing non-matching numbers while they figure things out.
Is it ok to nest views in this case?
Does it change things if the inner view contains a further, important view that contains relevant prices (i.e. you're "always" supposed to use this view when determining prices)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
嵌套视图的主要问题是查询优化器更有可能感到困惑并产生次优计划。除此之外,在视图上使用视图没有特定的开销,除非它们做了优化器无法将谓词下推的事情。
这意味着最好的选择是尝试嵌套视图。查看您是否从报告中获得了合理的查询计划。如果它确实引起问题,那么您可能必须重新考虑您的策略。
The main problem with nesting views is that the query optimiser is more likely to get confused and produce a sub-optimal plan. Apart from this, there is no specific overhead to using views on views unless they do something that the optimiser can't push predicates down into.
This means that the best option is to try the nested views. See if you get sensible query plans out of the reports. If it does cause problems then you may have to re-think your strategy.
我将从最佳实践的角度回答:
只有几次我会暂停使用视图上的视图。
嵌套似乎已经失控……深度超过 3 层。我嵌套的原因是为了让代码更容易维护。一旦我开始讲到这一点,我就开始感觉有点太复杂了,难以理解。
嵌套使用分析函数的视图。出于某种原因,我个人在使用分析函数嵌套视图方面没有很好的经验。
本质上进行全面扫描的嵌套视图。虽然我认为查询优化器可能足够聪明来处理这个问题,但当我检查视图的逻辑时,它看起来是错误的。
性能是一个非常令人担忧的问题。这并不是说优化器可能会出错,而是说在我发布它之前,我将对其进行测试,看看我是否无法找到更快的方法来做到这一点。
除此之外,我已经非常成功地使用了视图上的视图。
I'll just answer from a best practices perspective:
There are only a few times I would pause about using Views on Views.
Nesting seems to be getting out of hand ... like over 3 levels deep. The reason I am nesting is to make the code easier to maintain. As soon as I start getting to this point it starts feeling a little too complicated to understand.
Nesting a view which uses analytical functions. I've personally, for one reason or another, not had very good experience with nesting views with analytical function.
Nesting views that do full scans by nature. While I think the the query optimizer is probably smart enough to handle this it just looks wrong to me when I'm reviewing the logic of the view.
Performance is a great concern. This is not to say the optimizer might get it wrong but this is to say before I release it, I'm going to test it to see if I can't figure a faster way to do it.
Other than that I've used views on views quite successfully.
我认为您正处于滑坡上,代码重用和性能将发生冲突。您可以尝试一下,看看它对性能的影响有多大。我们这里有几个数据库,它们在视图之上堆叠了视图,坦率地说,性能很糟糕,现在每个参与的人都希望他们没有这样设计。
I think you are on the slippery slope here where code reuse and performance are going to clash. You can try it and see how badly it wil affect performance. We have a couple of databases here where they have stacked views on top of views and frankly the performance is miserable and now everyone involved wished thhat they had not designed that way.
编码时间、代码的易用性或质量以及性能之间总是需要权衡。
嵌套视图确实很容易编码,并且在适当的情况下,也使其易于阅读。它还可以减少时间。可以说,它会降低质量并经常降低性能……但降低了多少?
这都是主观的。如果有道理,那就跟着它走吧。不要过早优化您的代码。
There's always a tradeoff between coding time, ease or quality of code, and performance.
Nesting views is really easy to code and, given the right circumstances, makes it easy to read. It can also reduce time. It's arguably reducing the quality and often reduces performance... but by how much?
It's all subjective. If it makes sense, roll with it. Don't prematurely optimize your code.
最佳实践并不总是涵盖所有内容。我认为你有一个明确的理由来嵌套它们,就这一次。
Best practice doesn't always cover everything. I think you have a clear-cut justification for nesting them, just this once.
我在 Oracle 10g R2 中将视图嵌套了 3 层。性能似乎与视图中的选择语句相关,而不是与视图深度相关。特别是“IN”子句似乎造成了很多麻烦。
I'm nesting views 3 levels deep in Oracle 10g R2. Performance seem corelate to the select statements in the views, rather than the view depth. In particular the "IN" clause seems to be causing a lot of trouble.
在构建复杂的数据库查询的过程中值得注意的是,有时嵌套视图是最好的 - 例如,如果您需要在 2 列上构建任何数学运算符,例如 SUM(Col1, Col2) ,它可能会更好嵌套视图,使总和本身就是一列,而不必执行类似
“SELECT Total / SUM(Col1, Col2), SUM(Col1, Col2) * 2, Col1 / SUM(Col1, Col2) ... “
但是我不确定我是否理解 100% - 为什么需要 2 个视图?难道两个用户都不能查看第一个视图并在该视图之上的另一层视图中导出进一步的处理吗?
It's also a good thing to note in the process of building complicated database queries sometimes nested views are the best thing - for one example, if you need any math operator built on 2 columns, for instance SUM(Col1, Col2) it can be better to nest views so that the sum is a column in itself instead of having to do something like
"SELECT Total / SUM(Col1, Col2), SUM(Col1, Col2) * 2, Col1 / SUM(Col1, Col2) ..."
However I'm not sure I understand 100% - Why are there 2 views needed? Can't both users look at the 1 view and further processing be derived in a view another layer above that one?
使用视图的最佳理由是:
我确实意识到它还可以帮助简化更复杂的查询,但您会习惯它。您可能会发现用户定义的函数(表)可能是更好的解决方案。无论哪种方式,性能都会受到影响。
The best reasons to use a view would be to:
I do realize it can also help to simplify a more complex query, but you get use to it. You may find that a user defined function (table) may be a better solution. Either way, performance will take a hit.
嵌套视图是有意义的。请注意不要让它们太笼统。
我确实看到一个系统有一个视图,其中明确提到了 14 个表,其中一些与外部自联接连接,一些“表”本身就是视图。我不太喜欢它,但 DBMS 处理它的能力出奇地好(考虑到那是在 80 年代末)。许多模式是由数据建模工具机器生成的。
外连接表示法特定于 Informix(它现在也支持 SQL 标准表示法)。
请注意,IBB_V_Post_Resp2 和 IBB_V_Proj_Co2 本身都是视图。
事实上,IBB_V_Proj_Co2 是一个 3 表视图,具体细节未知,但
形式:
这意味着 IBB_V_Project 视图有一个外部自连接
IBB_项目。 IBB_V_Post_Resp2 视图可能涉及 3 个表
(我的笔记有点不清楚,早在 1993 年,当我记录这些信息时)。
Zzzz_Iref 列是 SERIAL 或 INTEGER 外键
引用 SERIAL 键。
主视图定义引用了 14 个表,其中有 4 个内连接和 9 个表
外连接。当考虑到交叉引用的视图时,有
总共18张表,有7个内连接和10个外连接。
Nested views can make sense. Just be careful that you don't make them too general.
I did see a system that had a view with 14 tables mentioned explicitly, some of them connected with outer self-joins, and some of the 'tables' were themselves views. I didn't like it much, but the DBMS coped with it astonishingly well (given that it was back in the late 80s). A lot of the schema was machine generated by a data modelling tool.
The outer join notation is specific to Informix (which now supports the SQL standard notation too).
Note that IBB_V_Post_Resp2 and IBB_V_Proj_Co2 are both themselves views.
In fact, IBB_V_Proj_Co2 was a 3-table view, exact details unknown but of
the form:
This means that the IBB_V_Project view has an outer self-join on
IBB_Project. The IBB_V_Post_Resp2 view probably involved 3 tables
too (my notes on that were a bit unclear, way back in 1993, when I recorded this information).
The Zzzz_Iref columns were either SERIAL or INTEGER foreign keys
referencing a SERIAL key.
The primary view definition refers to 14 tables, with 4 inner joins and 9
outer joins. When the cross-referenced views are taken into account, there
are 18 tables in total, with 7 inner joins and 10 outer joins.
真的不想陷入整个嵌套视图的事情,
想一想这个想法...你试图加入到一个表中以查找不匹配...我会使用 Oracle 函数“减”.. ..MINUS 从第一个表中选择元素,然后删除第二个 SELECT 语句也返回的行。
选择号码
FROM (SELECT 1 AS 编号
来自双
联合所有
选择 2 作为编号
来自双
联合所有
选择 3 作为编号
FROM DUAL) base_view
MINUS
SELECT 2 AS num
来自双
don't really want to get caught up in the whole nested view thing
have a think about this for an idea...your trying to join onto a table to find mismatches...i would use the Oracle function 'minus'....MINUS selects elements from the first table and then removes rows that are also returned by the second SELECT statement.
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