Oracle View 会计算您不打算查询的字段吗?

Does Oracle View calculate fields you are not trying to query?

我正在尝试优化查询的性能。问题是: 假设我们有视图 X。它有属性 A、B、C。 C是计算字段。

假设我想通过查询“Select A,B from X where A = 'some condition'”来尝试优化,然后如果我需要 C,我可以稍后用更小的子集计算它数据以提高性能。

我的问题是这会有帮助吗?或者当我进行初始查询时,无论我是否正在查询该 attr,Oracle 视图都会计算 C 吗?因此为了优化我必须从视图中删除这些计算?

SQL 是一种 描述性 语言,而不是 程序性 语言。数据库优化器实际上决定了执行。

对于您的场景,优化器有两个合理的选择:

  1. 过滤行,然后计算过滤后的值。
  2. 先计算值再过滤

Oracle 有一个很好的优化器,所以我希望它能考虑这两种可能性。它会选择对您的查询具有最佳性能的那个。

如果您仍然只需要 c 返回一些行,那么延迟计算可能是值得的 如果它真的非常昂贵。但是,这将是一个不寻常的优化。

简短的回答是 是的,它有助于 到 select 只有视图中的有限列列表 - 两者都是 CPU(值计算) 和存储。

在可能的情况下,Oracle 优化器会完全删除 视图定义并将其合并到带下划线的 table 中。

因此查询中 未引用 的视图列根本未被访问。

这是一个简单的例子

create table t as
select rownum a, rownum b, rownum c from dual 
connect by level = 10;

create or replace view v1 as
select  a,  b, c/0 c from t;

我正在使用 零除法 模拟 复杂计算 以查看该值是否被计算。

最好的检查方法是运行查询并查看执行计划

select a, b from v1
where a = 1;

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    26 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T    |     1 |    26 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("A"=1)
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "A"[NUMBER,22], "B"[NUMBER,22]

在项目信息中可见,只有 AB 列被引用 - 因此没有对 C 列进行计算。

甚至反过来也行;如果您首先具体化视图,然后进行行过滤。我正在用以下查询模拟它 - 不是那个 MATERALIZE 提示 实现 查询中使用的临时 table 中的所有视图行。

with vv as (
select /*+ MATERIALIZE */ a,b from v1)
select a, b from vv
where a = 1;

----------------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name                        | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |                             |     1 |    26 |     5   (0)| 00:00:01 |
|   1 |  TEMP TABLE TRANSFORMATION |                             |       |       |            |          |
|   2 |   LOAD AS SELECT           | SYS_TEMP_0FD9D6605_5E8CE554 |       |       |            |          |
|   3 |    TABLE ACCESS FULL       | T                           |     1 |    26 |     3   (0)| 00:00:01 |
|*  4 |   VIEW                     |                             |     1 |    26 |     2   (0)| 00:00:01 |
|   5 |    TABLE ACCESS FULL       | SYS_TEMP_0FD9D6605_5E8CE554 |     1 |    26 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------------- 
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   4 - filter("A"=1)
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "A"[NUMBER,22], "B"[NUMBER,22]
   2 - SYSDEF[4], SYSDEF[0], SYSDEF[1], SYSDEF[96], SYSDEF[0]
   3 - "A"[NUMBER,22], "B"[NUMBER,22]
   4 - "A"[NUMBER,22], "B"[NUMBER,22]
   5 - "C0"[NUMBER,22], "C1"[NUMBER,22]

您再次在投影信息中看到未引用列 C

什么不起作用,您应该避免使用 select * .. 实现视图 - 这当然会失败。

with vv as (
select /*+ MATERIALIZE */ * from v1)
select a, b from vv
where a = 1;