11GConcepts(翻译第七章)SQL(结构化查询语言)(五)

2014-11-24 10:18:21 · 作者: · 浏览: 17
MENT | | 26 | 182

| 1| TABLE ACCESS BY INDEX ROWID |EMPLOYEES | 26 | 182

|* 2 | INDEX RANGE SCAN |EMP_DEPARTMENT_IX | |

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

上面例子中的执行计划显示了优化器选择了employees.department_id列上面的索引 来寻找employees表中department_id大于50的 的前25行。优化器使用从索引中检索到的rowid,用来到employees表中检索对应的记录,然后返回它们到客户端。第一条记录的几乎瞬间就取回了

下面例子显示了相同的语句,但是没有使用 优化器 hint

SELECT employee_id, department_id

FROM hr.employees

WHERE department_id > 50;

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

| Id | Operation | Name | Rows | Bytes | Cos

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

| 0 |SELECT STATEMENT | | 50 | 350 |

|* 1 | VIEW |index$_join$_001 | 50 | 350 |

|* 2 | HASH JOIN | | | |

|* 3 | INDEX RANGE SCAN |EMP_DEPARTMENT_IX | 50 | 350 |

| 4| INDEX FAST FULL SCAN|EMP_EMP_ID_PK | 50 | 350 |

上面例子的执行计划,通过join两个索引,然后尽可能快的返回所请求的记录。而不是重复的从索引到表像上上一个例子所示。优化器选择对EMP_DEPARTMENT_IX进行range scan 找出所有department_id大于50的行,然后把这些行放到 一个hash table。优化器然后选择读EMP_EMP_ID_PX索引,循环这一索引中的每个行,去探测hash table,去找department id

在这个情况下,数据库在索引EMP_DEPATMENT_IX 的range scan完成以前,是没办法将第一行返回给客户端的.因此,这个执行计划获取第一条记录的时间会长于前面的执行计划。前面的执行计划通过索引上的rowid来访问表,而本执行计划则是使用多块I/O,在大量读取中使用,这种读取使的整个结果集的最后一行返回的时间最快。

Overview of SQL processing

这个小节解释了Oracle数据库是如何处理SQL语句的。具体来说,解释了DDL语句创建对象,DML语句修改对象,和查询是检索数据 等在数据库中的处理方式。

Stages of SQL Processing

下图描述了SQL处理的常规阶段:parsing(解析),optimization(优化),row source generation(产生行源),execution(执行)。数据库可能会忽略其中的一些阶段,这取决于具体的语句。

\

SQL Parsing

如上图所示,SQL处理的第一阶段是parsing(解析)。这个步骤涉及到将SQL语句分片,然后放入到一个数据结构,这样后面的步骤才能对它进行处理。

当一个应用程序发送了一条SQL语句,应用程序产生一个parse call到数据库去做语句执行的预备工作。Parse call打开或创建一个cursor,cursor是 session-specific(具体会话)的private SQL area的句柄,private SQL area持有解析后的SQL语句以及其他的处理信息。Cursor和private SQL area都在PGA中。

在parse call的过程中,数据库执行了以下检查:

·Syntax Check

·Semantic Check

·Shared Pool Check

预先检查将在语句执行以前就识别出错误。有一些错误是没办法在解析阶段捕获的,比如数据库会遇到死锁,或数据转换时的错误,不过它们仅在语句执行过程中发生。

SyntaxCheck(语法检查)

Oracle数据库检查每个SQL语句,保证语法正确。一个语句违犯了 well-formed SQL语法规则,将无法通过检查。举个例子,下面的语句将失败,因为关键字FROM拼写错误为FORM:

SQL> SELECT * FORM employees;

SELECT * FORM employees

*

ERROR at line 1:

ORA-00923: FROM keyword not found whereexpected

SemanticCheck(语义检查)

一个语句的语义,就是它的含义。因此语义检查确定一个语句是否是有意义的,举个例子,语句中的对象和列是否都存在。一个语法正确的语句可能会在语义检查阶段失败,像下面例子显示的,对于一个不存在的表,进行的查询:

SQL> SELECT * FROM nonexistent_table;

SELECT * FROM nonexistent_table

*

ERROR at line 1:

ORA-00942: table or view does not exist

SharedPool Check(共享池检查)

在解析过程中,数据库会执行一个shared pool check来确定它是否可以跳过 语句解析中资源密集的步骤。为此,数据库使用了一个hashing 算法来为每个SQL语句都产生一个hash值。语句的hash值叫 SQL ID,在V$SQL.SQL_ID列显示。

但一个用户提交一个SQL语句,数据库会检索所有的shared SQL area,来查看是否存在相同hash值的已经解析过的语句。一个SQL语句的hash值和下面这些值是有区别的:

·Memory address for the statement(语句的内存地址)

Oracle数据库使用SQL_ID 在一个查阅表中 执行一个带键值的读取。通过这种方式,数据库获取该语句所有可能的内存地址。

·语句一个执行计划的hash 值

一个SQL语句可以在shared pool中有多个计划。每个计划都有一个不同的hash值。如果相同的SQL_ID 有多个计划hash 值,那么数据库则会知道针对这个SQL_ID存在多个计划。

解析操作分为下面类型,依赖于提交的语句类型以及hash检查的结果:

·Hard parse(硬解析)

如果Oracle数据库不能重用已经存在的,那么它必须对语句创建一个新的可执行版本。这个操作称之为硬解析,或一个library cache miss。数据库对于DDL语句 总是执行硬解析。

在硬解析的执行过程中,数据库会访问很多次library cache和data dictionary cache 来检查数据字典。当数据库访问这些区域,它使用了一个串行化的装置,称之为latch 在所请求的对象上。这样它们的定义就不会发生变化。Latch争用会减少并发,以及增加语句的执行时间。

·Soft parse(软解析)