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 是一种 描述性 语言,而不是 程序性 语言。数据库优化器实际上决定了执行。
对于您的场景,优化器有两个合理的选择:
- 过滤行,然后计算过滤后的值。
- 先计算值再过滤
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]
在项目信息中可见,只有 A
和 B
列被引用 - 因此没有对 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;
我正在尝试优化查询的性能。问题是: 假设我们有视图 X。它有属性 A、B、C。 C是计算字段。
假设我想通过查询“Select A,B from X where A = 'some condition'”来尝试优化,然后如果我需要 C,我可以稍后用更小的子集计算它数据以提高性能。
我的问题是这会有帮助吗?或者当我进行初始查询时,无论我是否正在查询该 attr,Oracle 视图都会计算 C 吗?因此为了优化我必须从视图中删除这些计算?
SQL 是一种 描述性 语言,而不是 程序性 语言。数据库优化器实际上决定了执行。
对于您的场景,优化器有两个合理的选择:
- 过滤行,然后计算过滤后的值。
- 先计算值再过滤
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]
在项目信息中可见,只有 A
和 B
列被引用 - 因此没有对 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;