SQL语句的执行流程语法分析
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、执行流程</a></li><li><a href="#_label1">二、建立连接</a></li><li><a href="#_label2">三、预处理器</a></li><li><a href="#_label3">四、解析器</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_0">4.1 词法分析</a></li><li><a href="#_lab2_3_1">4.2 语法分析</a></li><li><a href="#_lab2_3_2">4.3 语义分析</a></li></ul><li><a href="#_label4">五、优化器</a></li><ul class="second_class_ul"></ul><li><a href="#_label5">六、执行器</a></li><ul class="second_class_ul"></ul><li><a href="#_label6">七、返回结果</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、执行流程</h2><table><tbody><tr><th>阶段</th><th>主要功能</th><th>关键组件</th></tr><tr><td><strong>1. 建立连接</strong></td><td>身份验证、权限检查</td><td>连接器</td></tr><tr><td><strong>2. 预处理器</strong></td><td>缓存检查、SQL预处理</td><td>查询缓存</td></tr><tr><td><strong>3. 解析器</strong></td><td>词法分析、语法分析、语义检查</td><td>解析器</td></tr><tr><td><strong>4. 优化器</strong></td><td>生成最优执行计划</td><td>查询优化器</td></tr><tr><td><strong>5. 执行器</strong></td><td>按计划执行查询</td><td>执行引擎</td></tr><tr><td><strong>6. 返回数据</strong></td><td>结果返回、资源清理</td><td>结果处理器</td></tr></tbody></table>
<p class="maodian"><a name="_label1"></a></p><h2>二、建立连接</h2>
<p>当应用程序需要执行SQL语句时,首先需要与数据库服务器建立连接:</p>
<div class="jb51code"><pre class="brush:sql;"># 建立MySQL连接
mysql -h localhost -u username -p database_name</pre></div>
<p>连接阶段的主要工作:身份验证和分配连接资源。</p>
<p class="maodian"><a name="_label2"></a></p><h2>三、预处理器</h2>
<p>预处理器主要负责SQL语句的预处理工作:</p>
<ul><li>在MySQL 8.0之前的版本中,预处理器首先检查查询缓存。</li><li>读取到这条SQL语句的基本信息。</li><li>去除注释和多余空格,大小写标准化。</li></ul>
<p class="maodian"><a name="_label3"></a></p><h2>四、解析器</h2>
<p>分析器负责对SQL语句进行全面的分析和检查:</p>
<p class="maodian"><a name="_lab2_3_0"></a></p><h3>4.1 词法分析</h3>
<p>将SQL语句分解为一系列的标记:</p>
<div class="jb51code"><pre class="brush:sql;">SELECT name, age FROM users WHERE age > 18;</pre></div>
<p><strong>词法分析结果:</strong></p>
<table><tbody><tr><th>标记</th><th>类型</th><th>说明</th></tr><tr><td><code>SELECT</code></td><td>关键字</td><td>SQL关键字</td></tr><tr><td><code>name</code></td><td>标识符</td><td>字段名</td></tr><tr><td><code>,</code></td><td>分隔符</td><td>逗号分隔符</td></tr><tr><td><code>age</code></td><td>标识符</td><td>字段名</td></tr><tr><td><code>FROM</code></td><td>关键字</td><td>SQL关键字</td></tr><tr><td><code>users</code></td><td>标识符</td><td>表名</td></tr><tr><td><code>WHERE</code></td><td>关键字</td><td>SQL关键字</td></tr><tr><td><code>></code></td><td>操作符</td><td>比较操作符</td></tr><tr><td><code>18</code></td><td>数值常量</td><td>整数字面量</td></tr></tbody></table>
<p class="maodian"><a name="_lab2_3_1"></a></p><h3>4.2 语法分析</h3>
<p>根据SQL语法规则构建抽象语法树(AST):</p>
<div class="jb51code"><pre class="brush:sql;"> SELECT
/ \
字段列表 FROM子句
/ \ |
name age users表
|
WHERE子句
|
条件表达式
/ | \
age > 18</pre></div>
<p class="maodian"><a name="_lab2_3_2"></a></p><h3>4.3 语义分析</h3>
<p>进行语义层面的检查和验证:</p>
<ul><li>表存在性检查:查询表信息是回去数据库查询是否有这个表。</li><li>字段存在性检查:查询字段信息是回去数据库表查询是否有这个字段。</li><li>权限检查:设计表或数据库的删除要检查当前用户的权限。</li><li>约束检查:查询表的主外键、不为空、唯一等约束条件。</li></ul>
<p class="maodian"><a name="_label4"></a></p><h2>五、优化器</h2>
<p>选择代价最小的执行计划,从而提高 SQL 执行效率,场见的优化场景如下:</p>
<ul><li>确定多表连接顺序</li><li>是否使用索引?使用哪个索引?</li><li>选择合适的执行算法(嵌套循环 / 哈希连接 / 排序 / 归并等)</li></ul>
<p>示例SQL:</p>
<div class="jb51code"><pre class="brush:sql;">SELECT name FROM student WHERE age > 18;</pre></div>
<p>执行器的执行过程可能如下:</p>
<ul><li>使用 B+ 树索引快速定位满足 age > 18 的主键 ID;</li><li>根据主键回表获取 name 字段;</li><li>逐行拼装结果集并返回给客户端。</li></ul>
<p class="maodian"><a name="_label5"></a></p><h2>六、执行器</h2>
<p>根据执行计划,具体执行 SQL。<br /><strong>步骤:</strong></p>
<ul><li>访问表、索引,执行 WHERE 条件过滤</li><li>做连接操作、聚合、排序等</li><li>将结果写入结果集返回客户端</li></ul>
<p class="maodian"><a name="_label6"></a></p><h2>七、返回结果</h2>
<p>查询执行完成后,将结果返回给客户端。<br />比如下面的 SQL:</p>
<div class="jb51code"><pre class="brush:sql;">SELECT id, name FROM user LIMIT 2;</pre></div>
<p>结果集在返回客户端前,格式如下:</p>
<div class="jb51code"><pre class="brush:plain;">+----+--------+
| id | name |
+----+--------+
| 1| Alice|
| 2| Bob |
+----+--------+</pre></div>
頁:
[1]