工业编码中sql是不可或缺的,编写或优化出高效率的SQL是码农的重要工作,了解SQL的处理过程可以让我们与数据库交互时游刃有余。下面是oracle数据库处理SQL的过程。

SQL处理

SQL处理是SQL语句的解析、优化、行源生成和执行。为了更快的处理数据,数据库会做一些缓存,从而省略这些阶段中的一些。
下图描述了SQL处理的一般阶段。
SQL执行过程

SQL解析

解析阶段包括将SQL语句段分割成其他例程可以处理的数据结构。数据库在应用程序指示时解析语句,这意味着只有应用程序而不是数据库本身可以减少解析次数。
当应用程序发出SQL语句时,应用程序对数据库发出一个解析调用,以准备执行语句。解析调用打开或创建游标,该游标是一个会话级别的保存特定解析SQL语句和其他处理信息的私有SQL区域的句柄。私有SQL区域包括SQL相关的信息:变量的值,查询执行的状态信息和执行的区域。游标和私有SQL区域在程序全局区域(PGA)中。
在解析调用期间,数据库执行以下检查:

语法检查:语法是否有效

SQL> SELECT * FORM employees;
SELECT * FORM employees
         *
ERROR at line 1:
ORA-00923: FROM keyword not found where expected

语义检查:语句是否有意义,例如,语句中的表和列是否存在。

SQL> SELECT * FROM nonexistent_table;
SELECT * FROM nonexistent_table
              *
ERROR at line 1:
ORA-00942: table or view does not exist

共享池检查

前面的检查标识在语句执行之前可以找到的错误。有些错误不能通过解析来捕获。例如,数据库只能在语句执行期间遇到数据转换中的死锁或错误。
在解析过程中,数据库执行共享池检查,以确定它是否可以跳过语句处理的资源密集型步骤。
为此,数据库使用哈希算法来为每个SQL语句生成哈希值。语句哈希值是在V$SQL.SQL_ID。这个哈希值在Oracle整个数据库的版本中是确定的,
因此在单个实例或不同实例中的相同语句具有相同的SQL_ID。
当用户提交SQL语句时,数据库搜索共享SQL区域(SGA),以查看现有的解析语句是否具有相同的哈希值。

SQL语句的哈希值与下列值不同:

语句的内存地址
Oracle数据库使用SQL_ID在查找表中执行键控读取。这样,数据库就可以获得语句的可能内存地址。
语句的执行计划的哈希值
SQL语句在共享池中可以有多个计划。通常,每个计划都有不同的哈希值。如果相同的SQL_ID具有多个计划哈希值,则数据库知道该SQL_ID存在多个计划。

根据提交的语句类型和哈希检查的结果,解析操作分为以下类别:

硬解析:DDL总是会执行硬解析

如果Oracle数据库不能重用现有代码,那么它必须构建一个新的可执行版本的应用程序代码。此操作称为硬解析或类库缓存缺失。
在硬解析过程中,数据库多次访问库缓存和数据字典缓存,以检查数据字典。当数据库访问这些区域时,它使用被调用对象上的闩锁的序列化设备(并发访问中保护SGA中的共享数据结构),这样它们的定义不会改变。锁存争用会增加语句执行时间并减少并发性。

软解析

软解析是任何解析而不是硬解析的语法。如果提交的语句与共享池中的可重用SQL语句相同,则Oracle数据库重用现有代码。代码的重用也被称为库缓存命中。
软解析可以根据它们执行的工作量而变化。例如,配置会话共享SQL区域有时可以减少软解析中的锁存量,使它们更加“软”。
一般来说,软解析优于硬解析,因为数据库跳过优化和行源生成步骤,直接执行。
SQL执行过程
如果检查确定共享池中的语句具有相同的哈希值,则数据库执行语义和环境检查,以确定语句是否具有相同的含义。相同的语法是不够的,例如两个schema中创建同名的表,就不能复用,必须进行硬解析。在这种情况下,优化器环境是可以影响执行计划生成的会话设置的总体性,例如工作区大小或优化器设置(例如,优化器模式)。考虑由单个用户执行的以下SQL语句序列

ALTER SESSION SET OPTIMIZER_MODE=ALL_ROWS;
ALTER SYSTEM FLUSH SHARED_POOL;               # optimizer environment 1
SELECT * FROM sh.sales;
ALTER SESSION SET OPTIMIZER_MODE=FIRST_ROWS;  # optimizer environment 2
SELECT * FROM sh.sales;
ALTER SESSION SET SQL_TRACE=true;             # optimizer environment 3
SELECT * FROM sh.sales;

在三个不同的优化器环境中执行相同的SELECT语句。因此,数据库为这些语句创建三个单独的共享SQL区域,并迫使每个语句进行硬解析。

SQL优化

在优化阶段,Oracle数据库必须对每一个唯一的DML语句执行至少一次的硬解析,并在该解析过程中执行优化。
数据库从不优化DDL,除非它包括一个DML组件,如需要优化的子查询。

SQL行源生成

行源生成器是从优化器接收最优执行计划并生成可由数据库其余部分使用的迭代执行计划的软件。执行计划(execution plan)是行源生成器的输出。
迭代计划是一个二进制程序,当由SQL引擎执行时,生成结果集。该计划采取的步骤组合的形式。每个步骤返回行集。下一步要么使用这个集合中的行,要么最后一步将行返回给发出SQL语句的应用程序。
行源是由执行计划中的步骤返回的行集,以及可以迭代处理行的控制结构。行源可以是连接或分组操作的表、视图或结果。
行源生成器生成行源树,该行源树是行源的集合。行源树显示以下信息:
语句引用的表的排序
语句中提到的每个表的访问方法
语句中联接操作影响的表的联接方法
数据操作,如过滤、排序或聚合

SQL执行

在执行过程中,SQL引擎执行行源生成器生成的树中的每一行源。此步骤是DML处理中唯一的强制步骤。
在执行过程中,如果数据不在内存中,则数据库从磁盘读取数据到内存。数据库还取出确保数据完整性所需的任何锁和锁存器,并记录SQL执行期间所做的任何更改。
处理SQL语句的最后阶段是关闭游标。

SELECT e.last_name, j.job_title, d.department_name 
FROM   hr.employees e, hr.departments d, hr.jobs j
WHERE  e.department_id = d.department_id
AND    e.job_id = j.job_id
AND    e.last_name LIKE 'A%';
Execution Plan
----------------------------------------------------------
Plan hash value: 975837011
--------------------------------------------------------------------------------
| Id| Operation                     | Name        |Rows|Bytes|Cost(%CPU)|Time  |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT              |             |  3 | 189 | 7(15)| 00:00:01 |
|*1 |  HASH JOIN                    |             |  3 | 189 | 7(15)| 00:00:01 |
|*2 |   HASH JOIN                   |             |  3 | 141 | 5(20)| 00:00:01 |
| 3 |    TABLE ACCESS BY INDEX ROWID| EMPLOYEES   |  3 |  60 | 2 (0)| 00:00:01 |
|*4 |     INDEX RANGE SCAN          | EMP_NAME_IX |  3 |     | 1 (0)| 00:00:01 |
| 5 |    TABLE ACCESS FULL          | JOBS        | 19 | 513 | 2 (0)| 00:00:01 |
| 6 |   TABLE ACCESS FULL           | DEPARTMENTS | 27 | 432 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------

SQL执行过程

Oracle数据库如何处理DML

大多数DML语句都有查询组件。在查询中,光标的执行将查询的结果放入一组称为结果集的行中。

如何获取行集

结果集行可以一次取一行,也可以成组取一行。
在提取阶段,数据库选择行,如果查询请求,则命令行。每个连续的FETCH检索结果的另一行,直到最后一行被提取为止。
通常,数据库无法确定查询所要检索的行数,直到获取最后一行为止。Oracle数据库响应于fetch调用检索数据,以便数据库读取的行越多,它执行的工作就越多。对于某些查询,数据库尽可能快地返回第一行,而对于其他查询,则在返回第一行之前创建整个结果集。

读一致性

一般来说,查询通过使用Oracle数据库读取一致性机制来检索数据,这保证了查询读取的所有数据块都与单个时间点一致。
读取一致性使用撤消数据来显示过去版本的数据。例如,假设查询必须在全表扫描中读取100个数据块。查询处理前10个块,而在不同会话中的DML修改块75。当第一个会话到达块75时,它实现了更改,并使用撤消数据来检索旧的、未修改的数据版本,并在内存中构建块75的非当前版本。

数据变化

必须更改数据的DML语句使用读取一致性来检索仅在修改开始时匹配搜索标准的数据。
之后,这些语句在当前状态下检索数据块并进行必要的修改。数据库必须执行与修改数据相关的其他操作,例如生成重做和撤消数据。

Oracle数据库如何处理DDL

Oracle数据库处理DDL与DML不同。
例如,当创建表时,数据库不会优化CREATETABLE语句。相反,Oracle数据库解析DDL语句并执行命令。
数据库处理DDL的方式不同,因为它是在数据字典中定义对象的一种手段。通常,Oracle数据库必须解析并执行许多递归SQL语句来执行DDL语句。假设您创建一个表如下:
CREATE TABLE mytable (mycolumn INTEGER);
通常,数据库将运行几十个递归语句来执行前面的语句。递归SQL将执行如下操作:

  在创建CREATETABLE语句之前发出提交
  验证用户权限是否足以创建表
  确定表应该驻留在哪个表空间中
  确保尚未超过表空间配额
  确保架构中没有对象具有相同的名称
  将定义表的行插入到数据字典中
  如果DDL语句成功或如果没有回滚,则发出提交。

小结

	现有连接 ---用户进程 执行SQL操作
	传递给服务器进程的PGA --处理SQL操作 --- 分析任务 ---语法 语义 共享检查
	---到SGA的共享池
	
	SGA的共享池 ---查询优化器操作 ---数据buffer data buffer cache ---datafile 
	---得到行数据---行数据是否需要再次处理--需要再次处理的--交给PGA处理 
	---返回服务器进程---结果传输到用户进程 ---用户看到执行结果。
	
	SGA的共享池 ---查询优化器操作 ---数据buffer data buffer cache ---datafile 
	---得到行数据---行数据是否需要再次处理--不需要再次处理的
	---返回给服务器进程---结果传输到用户进程 ---用户看到执行结果。

官方原文

oracle doc

相关文章: