`
bianxq
  • 浏览: 94563 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

Oracle's Query Transformer

阅读更多

Oracle优化器的工作主要分成3步。。。

Oracle优化器的工作主要分成3:

 

首先, 优化器会尝试把复杂的SQL语句转化较为简单的SQL语句, 通常倾向于转化为表的连接方式.

 

然后, 优化器会对依据统计信息对SQL语句进行估量, 这些估量主要包括3个方面: Selectivity,

 

CardinalityCost, 这三个方面是相互相关的.

 

最后, 优化器会尝试各种执行计划并给出一个代价最低的计划.

 

 

要想理解优化器如何得到最后的执行计划, 首先就要理解被优化的SQL语句的结构, 这是浅显的道理. 但由于Oracle优化器有时候会对我们的SQL语句进行转化, 这就意味着优化器最终所优化器的对象, 并不一定就是我们最初提供的那个语句. 所以, 现在我们将会开始介绍优化器对SQL语句进行转化时所遵循的一些机制. 由于优化器的复杂远远超出我的认知, 这里我不可能列出所有的机制, 不过我希望至少能够达到这样的效果:

 

 

假设您对优化器了解甚少, 在我介绍之前, 您对于某些执行计划的看法可能是:

 

我实在不理解这个该死的执行计划是怎么来的

 

我希望在我介绍之后, 您的看法会转变为:

 

我还是不完全理解这个该死的执行计划是怎么来的, 不过我至少知道这是优化器转化的结果, 我觉得我可以尝试对我的SQL改变一下格式或者使用一些提示

 

 

闲话少叙, 正式开始:

 

Oracle的优化器对SQL转化的手段包括5, 我们接下来会对这个方面分别进行说明:

 

  • View Merging

     

  • Predicate Pushing

     

  • Subquery Unnesting

     

  • Query Rewrite with Materialized Views

     

  • OR-expansion

     

 

对于每一部分, 我打算都先给大家看一看Oracle官方文档的权威说法 (通常都是摘自Oracle Database Performance Tuning Guide 10g Release2), 然后通过实际的例子进一步说明:

 

 

2.1 View Merging

 

2.1.1 View Merging定义

 

Each view referenced in a query is expanded by the parser into a separate query block. The query block essentially represents the view definition, and therefore the result of a view. One option for the optimizer is to analyze the view query block separately and generate a view subplan. The optimizer then processes the rest of the query by using the view subplan in the generation of an overall query plan. This technique usually leads to a suboptimal query plan, because the view is optimized separately from rest of the query.

 

 

The query transformer then removes the potentially suboptimal plan by merging the view query block into the query block that contains the view. Most types of views are merged. When a view is merged, the query block representing the view is merged into the containing query block. Generating a subplan is no longer necessary, because the view query block is eliminated.

 

 

对于SQL里的视图, 优化器可以选择先对视图代表的查询单独优化并生成view本身的执行计划, 在把这个计划和SQL语句其他的部分合并在一起生成最终的执行计划, 当然这种技术往往会产生一个不是最好的计划, 因为视图的优化是单独考虑了, 而没有放到整个SQL环境中通盘考虑.

 

Oracle的查询优化器则可以帮助我们把视图代表的查询mergeSQL的其他部分当中, 从而可以更全面的考虑SQL的执行计划.

 

 

那么优化器的view merging操作到底是怎么实现的呢? 我们先看一个简单的例子.

 

首先我们使用的是Oracle 9i提供的一个sample schema: HR, 创建脚本下载:

 

http://gdcckm.chn.hp.com/teams/ams/asdba/dbcommunity/Shared%20Documents/Others/hr_schema.zip

 

 

 

例一:

 

我们先对里面employees表视图:

 

CREATE VIEW emp_10

 

AS SELECT employee_id, last_name, job_id, manager_id, hire_date, salary,

 

commission_pct, department_id

 

FROM employees

 

WHERE department_id = 10;

 

 

我们针对视图emp_10做一个查询:

 

SELECT employee_id

 

FROM emp_10

 

WHERE employee_id > 170;

 

 

Execution Plan

 

----------------------------------------------------------

 

Plan hash value: 3659898230

 

 

-------------------------------------------------------------------------------------------------

 

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

 

-------------------------------------------------------------------------------------------------

 

| 0 | SELECT STATEMENT | | 1 | 7 | 2 (0)| 00:00:01 |

 

|* 1 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 1 | 7 | 2 (0)| 00:00:01 |

 

|* 2 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 1 | | 1 (0)| 00:00:01 |

 

-------------------------------------------------------------------------------------------------

 

 

Predicate Information (identified by operation id):

 

---------------------------------------------------

 

 

1 - filter("EMPLOYEE_ID">170)

 

2 - access("DEPARTMENT_ID"=10)

 

 

我们看到的执行计划里面已经看不到emp_10这个视图的名字, 因为视图已经被转化成了针对employees的查询, 转化后的语句应该是这样的(根据10053的输出):

 

 

SELECT "EMPLOYEES"."EMPLOYEE_ID" "EMPLOYEE_ID"

 

FROM HR."EMPLOYEES" "EMPLOYEES"

 

WHERE "EMPLOYEES"."DEPARTMENT_ID"=10 AND "EMPLOYEES"."EMPLOYEE_ID">170

 

 

如果我们使用hint来要求Oracle不要做view merging的话, 我们看到的执行计划应该是这样的:

 

 

SELECT /*+ no_merge(emp_10) */ employee_id

 

FROM emp_10

 

WHERE employee_id > 170;

 

 

 

 

Execution Plan

 

----------------------------------------------------------

 

Plan hash value: 1825255554

 

 

--------------------------------------------------------------------------------------------------

 

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

 

--------------------------------------------------------------------------------------------------

 

| 0 | SELECT STATEMENT | | 1 | 13 | 2 (0)| 00:00:01 |

 

| 1 | VIEW | EMP_10 | 1 | 13 | 2 (0)| 00:00:01 |

 

|* 2 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 1 | 25 | 2 (0)| 00:00:01 |

 

|* 3 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 1 | | 1 (0)| 00:00:01 |

 

--------------------------------------------------------------------------------------------------

 

 

Predicate Information (identified by operation id):

 

---------------------------------------------------

 

 

2 - filter("EMPLOYEE_ID">170)

 

3 - access("DEPARTMENT_ID"=10)

 

 

我们会在10053 trace中看到SQL的结构是:

 

SELECT /*+ NO_MERGE ("EMP_10") */ "EMP_10"."EMPLOYEE_ID" "EMPLOYEE_ID"

 

FROM

 

(SELECT "EMPLOYEES"."EMPLOYEE_ID" "EMPLOYEE_ID" FROM HR

 

."EMPLOYEES" "EMPLOYEES" WHERE "EMPLOYEES"."DEPARTMENT_ID"=10 AND "EMPLOYEES"."EMPLOYEE_ID">170) "EMP_10"

 

 

这里我们看到视图是单独处理的, 不过值得一提的是exployee_id > 170这个条件也被加入视图中事先处理了, 这就涉及到了SQL语句转化另一种技术: Predicate Pushing, 我们会在后面再介绍.

 

 

当然, 由于这是一个最简单的例子, 所以你会发现不管做不做merging, 执行计划的cost都是一样的.

 

但是如果你尝试稍微复杂的例子, 你就比较看到一些区别了.

 

 

例二:

 

 

CREATE OR REPLACE VIEW avg_salary_view AS

 

SELECT department_id, AVG(salary) AS avg_sal_dept

 

FROM employees

 

GROUP BY department_id;

 

 

SELECT departments.location_id, avg_sal_dept

 

FROM departments, avg_salary_view

 

WHERE departments.department_id = avg_salary_view.department_id

 

AND departments.location_id = 2400;

 

 

Execution Plan

 

----------------------------------------------------------

 

Plan hash value: 2237210116

 

 

----------------------------------------------------------------------------------------------------

 

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

 

----------------------------------------------------------------------------------------------------

 

| 0 | SELECT STATEMENT | | 5 | 130 | 4 (25)| 00:00:01 |

 

| 1 | HASH GROUP BY | | 5 | 130 | 4 (25)| 00:00:01 |

 

| 2 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES | 10 | 70 | 1 (0)| 00:00:01 |

 

| 3 | NESTED LOOPS | | 5 | 130 | 3 (0)| 00:00:01 |

 

| 4 | TABLE ACCESS BY INDEX ROWID| DEPARTMENTS | 1 | 19 | 2 (0)| 00:00:01 |

 

|* 5 | INDEX RANGE SCAN | DEPT_LOCATION_IX | 1 | | 1 (0)| 00:00:01 |

 

|* 6 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 10 | | 0 (0)| 00:00:01 |

 

----------------------------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

 

---------------------------------------------------

 

 

5 - access("DEPARTMENTS"."LOCATION_ID"=2400)

 

6 - access("DEPARTMENTS"."DEPARTMENT_ID"="DEPARTMENT_ID")

 

 

SELECT /*+ no_merge(avg_salary_view) */ departments.location_id, avg_sal_dept

 

FROM departments, avg_salary_view

 

WHERE departments.department_id = avg_salary_view.department_id

 

AND departments.location_id = 2400;

 

 

Execution Plan

 

----------------------------------------------------------

 

Plan hash value: 725906304

 

 

-------------------------------------------------------------------------------------------------

 

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |

 

-------------------------------------------------------------------------------------------------

 

| 0 | SELECT STATEMENT | | 1 | 33 | 7 (29)| 00:00:01 |

 

|* 1 | HASH JOIN | | 1 | 33 | 7 (29)| 00:00:01 |

 

| 2 | TABLE ACCESS BY INDEX ROWID| DEPARTMENTS | 1 | 7 | 2 (0)| 00:00:01 |

 

|* 3 | INDEX RANGE SCAN | DEPT_LOCATION_IX | 1 | | 1 (0)| 00:00:01 |

 

| 4 | VIEW | AVG_SALARY_VIEW | 11 | 286 | 4 (25)| 00:00:01 |

 

| 5 | HASH GROUP BY | | 11 | 77 | 4 (25)| 00:00:01 |

 

| 6 | TABLE ACCESS FULL | EMPLOYEES | 107 | 749 | 3 (0)| 00:00:01 |

 

-------------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

 

---------------------------------------------------

 

 

1 - access("DEPARTMENTS"."DEPARTMENT_ID"="AVG_SALARY_VIEW"."DEPARTMENT_ID")

 

3 - access("DEPARTMENTS"."LOCATION_ID"=2400)

 

 

我们可以明显看出view merging发生与否导致的cost的区别, 不过这里更重要的是我们需要引入另一个概念:

 

 

 

2.1.2 Mergeable and Nonmergeable Views

 

并不是所有的视图都是可以做merging操作的, 一个视图是可以merging, 前提是这个视图不包含以下操作中的任何一个:

 

  • Set operators ( UNION , UNION ALL, INTERSECT, MINUS)

     

  • A CONNECT BY clause

     

  • A ROWNUM pseudocolumn

     

  • Aggregate functions (AVG, COUNT, MAX, MIN, SUM) in the select list

     

不包含以上操作的视图称为mergeable view, 否则称为nonmergeable view.

 

 

但是我上面的例子中的视图avg_salary_view就包括avg函数, 为什么它就可以merge, 这是因为视图中加入了group by

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    Oracle优化器介绍

    * 查询转换器(Query Transformer) * 评估器(Estimator) * 计划生成器(Plan Generator) 查询转换器的作用是改变查询语句的形式以产生较好的执行计划。Oracle 8i 开始有四种转换技术:视图合并(View Merging)...

    transformer 入门 培训

    Transformer的数据源通常是企业内部的数据库,例如Oracle。配置时,你需要编辑安装目录下的`cs7g.ini`文件,在`[Databases]`部分添加数据库连接信息,包括数据库的IP地址、服务名称、用户名和密码。如果需要连接多个...

    Oracle优化器介绍(精简完善版).doc

    1. **查询转换器(Query Transformer)**:负责调整查询语句形式,以利于生成更高效的执行计划。这包括视图合并、谓词推进、非嵌套子查询和物化视图查询重写等技术。 2. **评估器(Estimator)**:基于统计信息评估查询...

    Oracle调优实战执行计划

    - **查询转换器(Query Transformer)**:根据一系列规则对原始SQL语句进行转换,以便生成更有效的执行计划。 - **代价估算器(Estimator)**:使用统计信息来估算每种可能执行计划的成本,包括读取的数据量、处理...

    商务智能工具(Query Studio)

    - **数据源管理**:连接不同的物理数据库,如SQL Server、Oracle、DB2等,并为上层应用提供统一的数据接口。 - **模型构建**:支持构建复杂的OLAP模型,包括维度、度量等概念。 - **模型发布**:将构建好的模型发布...

    Cognos超详细中文教程

    Cognos 8的模块包括了Query Studio、Report Studio、Analysis Studio、Transformer和Framework Manager等,它们在Cognos体系中的位置应用和协作关系体现了Cognos对于业务智能的强大支持。 Cognos BI产品是基于Web...

    cognos 中级知识学习

    Cognos 中级知识学习主要涵盖多个核心组件的深入理解和应用,这些组件包括Cognos Configuration、Framework Manager、Transformer、Cognos Connection、Report Studio、Analysis Studio和Query Studio。以下是对这些...

    solr安装部署文档

    <entity name="selectfield" transformer="ClobTransformer" PK="ID" dataSource="ds-1" query="SELECT VWSFB_ZF_SELECTFIELD.*, VWSFB_ZF_SELECTFIELD.ZF_BH AS ID,VWSFB_ZF_SELECTFIELD.ZF_BH AS APPLYID,(SELECT...

    cognos配置注意事项

    Cognos BI Server的安装是核心步骤,它包括Query Studio、Report Studio和Analysis Studio,这些是Cognos的主要分析工具。 Transformer的安装用于数据转换,而BI Modeling (Framework Manager)则用于模型构建。在...

    Cognos培训讲义

    1. **数据源接入**:连接各类数据库,如SQL Server、Oracle、DB2等,以及平面文件(CSV、Excel)。 2. **元数据建模**:使用FrameworkManager和Transformer创建数据模型,定义维度、度量和层级关系。 3. **报表设计*...

    Cognos中级培训教程(1).ppt

    教程详细介绍了如何配置不同类型的数据库,如SQL Server、Oracle、DB2、Sybase和Cognos Content Database。每个数据库类型的配置都有特定的要求,例如字符集设置和JDBC驱动的放置。 **2.2 配置名字空间** 名字空间...

    Cognos中级培训教程.ppt

    在配置知识库时,讲师提到了几种常见数据库类型(如SQL Server、Oracle、DB2、Sybase和Cognos Content Database),并强调了针对不同数据库配置的注意事项,如字符集的选择和JDBC驱动的放置。配置名字空间涉及多种...

    1_cognos架构、相关组件及其安装和配置

    在Cognos 8 的数据流程中,数据首先从数据仓库或其他数据源(如Oracle、SQL Server等)被抽取,并通过Transformer 转换成PowerCube。接着,Framework Manager 对这些数据进行建模,创建出可供后续分析使用的业务模型...

    cognos中文教程

    - **数据源**:连接到不同的数据库系统,如SQL Server、Oracle等。 - **工程.cpf.xml**:项目配置文件,包含元数据信息。 #### 五、FrameworkManager的作用 - **多维模型构建**:使用Transformer创建多维数据...

    cognos中级培训教程

    3. **Transformer**:Transformer用于转换和聚合数据,是创建多维数据模型的重要部分。在这个阶段,学员会学习如何处理数据转换规则,优化数据加载过程,并进行数据预处理。 4. **Cognos Connection**:这是Cognos...

    Cognos高级知识库.ppt

    应用层由Cognos门户、Query Studio、Report Studio等组件组成,而数据层则连接到各种数据库和数据仓库,如IBM DB2、Oracle、Sysbase等。 2. **安装与配置**:Cognos的安装过程涉及网关、Web服务器、BI内容管理和...

    cognos高级知识库

    8. **高效率分析**:Cognos支持OLAP和ROLAP分析,以及基于OLAP的数据源,如Oracle OLAP、IBM DB2 OLAP等。同时,提供了事件管理和报警功能,以及指标(Metrics)管理,支持平衡计分卡和KPI的追踪。 9. **数据源集成...

    Cognos8培训课件(数据组织形式)

    Transformer用于设计多维数据结构,Framework Manager则用于组织和管理业务数据模型,Metric Studio协助企业进行绩效管理和监控,而Event Studio则能够预警可能影响业务的关键事件。 使用Cognos8时,用户通常会遵循...

    Cognos 8 概述

    - 如 SQL Server、Oracle 和 DB2 等数据库系统的连接设置。 #### 六、Cognos Connection Cognos Connection 是 Cognos 8 的 Web 应用程序接口,它为用户提供了一个统一的入口来访问所有 Cognos 8 的组件和服务。...

Global site tag (gtag.js) - Google Analytics