今天来当一下数据库,看一下sql到底在里面如何执行的?
不管是开发,还是运维,亦或者是产品。
多多少少会写sql,只不过有的人写得多,有的人写得少罢了。
但是你有想过,在数据库中,sql 到底是什么执行的吗?
最常见的两个数据库,Oracle和Mysql,今天就来看看执行流程。
这也算是常见的Java面试题了。
ok,开干。
让我们来看下第一个问题。
Oracle数据库,众所周知是付费的,小型企业基本上不用,如果你在开发中使用,我盲猜一手,你是不是尊贵的浦发银行的外包人员,又亦或者是xxx单位呢?
ok,开个玩笑,正式起航。
在Oracle中,SQL的执行过程可以简单分成以下的四个步骤:
解析(Parsing):当一个SQL语句被提交给Oracle数据库时,首先进行解析阶段。解析器会对SQL语句进行语法检查、语义检查,并生成解析树(Parse Tree)和内部数据结构。解析的结果会被用于后续的优化和执行阶段。
优化(Optimization):在解析完成后,优化器会根据解析树、表和索引的统计信息等,选择最佳的执行计划。执行计划是一个操作指令序列,它描述了数据库引擎在执行SQL语句时的具体操作方式,包括表的访问路径、连接方法、索引使用等。优化器会根据代价估算器评估不同执行计划的代价,并选择代价最小的执行计划。
执行(Execution):一旦优化器选择了执行计划,数据库引擎会按照执行计划的指令序列执行SQL语句。这包括打开表、获取锁、读取数据、执行计算等操作。数据库引擎会利用缓冲区高速缓存(Buffer Cache)中的数据来加速访问,并在必要时执行物理I/O操作。
提交(Commit):如果SQL语句是一个事务的一部分,在执行过程中可能会修改数据库中的数据。一旦SQL语句执行完毕,数据库引擎会等待事务的其他操作,然后根据事务的隔离级别,决定是否将修改的数据提交到数据库中。
优化器的作用是选择最佳的执行计划,以提高SQL语句的执行性能。
执行计划的质量对SQL语句的性能至关重要,因此在设计数据库结构、编写SQL语句和管理统计信息时,都需要考虑优化器的影响。
是不是看的难受,其实我也懒得看。
当执行一个SQL语句时,来看下步骤是咋样的:
解析(Parsing):
SELECT
|
└─── *
FROM
|
└─── employees
WHERE
|
└─── department_id = 10
优化(Optimization):
OPERATION OPTIONS OBJECT_NAME
------------------ --------------- -------------
SELECT STATEMENT
|
└─── TABLE ACCESS FULL employees
FILTER
|
└─── INDEX RANGE SCAN (department_id)
执行(Execution):
employee_id first_name last_name department_id
----------- ---------- --------- -------------
101 John Doe 10
102 Jane Smith 10
103 Mike Johnson 10
提交(Commit):
这只是一个简单的demo,实际开发环境中会涉及到表的大小,索引的使用情况,系统负载等等
而且
sql的执行过程还涉及到锁管理、并发控制、日志记录等其他的细节…这些东西以后再说。
软解析和硬解析都发生在解析(Parsing)阶段中。
软解析(Soft Parsing)是在第一次执行SQL语句时进行的解析过程。
当一个SQL语句首次被提交给Oracle数据库时,解析器会对SQL语句进行完整的解析过程,包括语法检查、语义检查、查询解析等,然后生成解析树和内部数据结构。
如果该SQL语句已经在共享池中存在对应的解析结果(即共享池中有缓存),则可以直接使用共享池中的解析结果,跳过软解析的过程,这称为共享池命中(Shared Pool Hit)。
硬解析(Hard Parsing)发生在以下情况:
优化器在解析完成后使用解析树和其他统计信息来进行优化决策,选择最佳的执行计划。因此,软解析和硬解析是解析阶段的一部分,它们发生在优化和执行阶段之前。
比如:
-- 第一次执行SQL语句,进行软解析和硬解析
SELECT * FROM employees WHERE department_id = 10;
-- 再次执行SQL语句,只进行软解析
SELECT * FROM employees WHERE department_id = 10;
在以上代码中,首次执行SQL语句 SELECT * FROM employees WHERE department_id = 10;
时,会进行软解析和硬解析的过程。
解析器会对SQL语句进行语法检查、语义检查,并生成解析树和内部数据结构。因为是首次执行,所以需要进行完整的解析过程,包括硬解析。解析器会生成解析树和执行计划,以供后续的优化和执行。
在第二次执行相同的SQL语句时,因为之前的解析结果已经存在于共享池中,解析器可以直接从共享池中获取解析结果,跳过硬解析过程。这称为共享池命中,只进行软解析的过程。共享池的存在可以减少重复解析的开销,提高查询性能。
插一嘴共享池的概念:
- 存储和管理共享的内部数据结构和SQL语句解析结果,以提高系统性能和减少重复解析的开销。
在MySQL中,SQL的执行过程可以分为以下5步骤:
语法解析(Parsing):当一个SQL语句被提交给MySQL数据库时,首先进行语法解析。解析器会对SQL语句进行语法检查和语义检查,确保语句的正确性。如果发现语法错误,解析器将报告错误信息。如果语法正确,解析器会生成解析树。
查询优化(Query Optimization):在解析完成后,MySQL会使用查询优化器对解析树进行优化。查询优化器会考虑执行计划中的多种可能性,选择最佳的执行计划。它会根据表的大小、索引的使用情况、查询的复杂性等因素进行评估,并尽量选择性能最好的执行计划。
执行计划生成(Execution Plan Generation):一旦查询优化器选择了执行计划,MySQL会生成执行计划,即执行SQL语句的具体操作方式。执行计划描述了表的访问路径、连接方法、索引使用等信息。
执行(Execution):MySQL根据生成的执行计划执行SQL语句。这包括打开表、获取锁、读取数据、执行计算等操作。MySQL会利用缓冲池(Buffer Pool)中的数据来加速访问,并在必要时执行物理I/O操作。
返回结果(Result Return):一旦SQL语句执行完毕,MySQL将返回执行结果给客户端。结果可以是一个结果集、影响的行数或其他执行信息,具体取决于SQL语句的类型。
来,继续看步骤:
语法解析(Parsing):
SELECT
|
└─── *
FROM
|
└─── employees
WHERE
|
└─── department_id = 10
查询优化(Query Optimization):
ID SELECT_TYPE TABLE TYPE POSSIBLE_KEYS KEY KEY_LEN REF ROWS FILTERED
-- ----------- --------- ---- ------------- -------- ------- --- ---- ---------
1 SIMPLE employees ref department_id key_dept 4 const 3 100.00
执行计划生成(Execution Plan Generation):
ID SELECT_TYPE TABLE TYPE POSSIBLE_KEYS KEY KEY_LEN REF ROWS FILTERED
-- ----------- --------- ---- ------------- -------- ------- --- ---- ---------
1 SIMPLE employees ref department_id key_dept 4 const 3 100.00
执行(Execution):
employee_id first_name last_name department_id
----------- ---------- --------- -------------
101 John Doe 10
102 Jane Smith 10
103 Mike Johnson 10
返回结果(Result Return):
MySQL的体系结构是基于C/S模型的,它包含多个组件和模块,每个模块负责不同的功能。下面是一些组件:
客户端(Client):
连接管理器(Connection Manager):
查询解析器和优化器(Query Parser and Optimizer):
执行引擎(Execution Engine):
存储引擎(Storage Engine):
日志管理(Logging):
缓存管理(Caching):
数据字典(Data Dictionary):
存储引擎(Storage Engine)是MySQL数据库中负责实际数据存储和检索的组件。
它定义了数据如何被组织、存储和访问。MySQL支持多个存储引擎,每个存储引擎具有不同的特性、性能和适用场景。以下是MySQL中常见的存储引擎:
InnoDB:
MyISAM:
Memory(或者称为 Heap):
NDB Cluster(也称为MySQL Cluster):
除了上述常见的存储引擎外,MySQL还支持其他存储引擎,如Archive、CSV、Blackhole等。
这里在插一嘴:
- Oracle没有存储引擎这个概念。他自己本身有一套统一的存储结构和架构,称之为Oracle存储结构。而且在Oracle中,数据是以表空间的形式进行存储和管理的。