MySQL 的 SQL 执行过程
MySQL 的 SQL 执行过程可以分为以下几个步骤:
连接建立阶段:
客户端与 MySQL 服务器建立 TCP 连接。 服务器进行身份认证,客户端提供用户名和密码。 认证通过后,建立连接。
SQL 解析阶段:
MySQL 服务器接收到 SQL 语句后,先进行语法分析和语义检查,确保语句的正确性。 MySQL 将 SQL 语句解析为内部的执行计划,即执行的查询计划。
查询优化阶段:
MySQL 根据查询的特点和数据库的统计信息,进行查询优化,选择最优的执行计划。 包括选择合适的索引、优化连接顺序、避免全表扫描等操作。
执行计划生成阶段:
MySQL 根据查询优化的结果,生成最终的执行计划。 执行计划包括具体的执行步骤、访问数据的方式、使用的索引等信息。
执行阶段:
MySQL 根据生成的执行计划,执行 SQL 查询。 查询过程中可能涉及到从磁盘读取数据、执行计算、排序、聚合等操作。
结果返回阶段:
MySQL 将查询结果返回给客户端。 客户端接收到结果后,可以进行进一步的处理或展示。
连接关闭阶段:
客户端和服务器通信结束后,可以选择断开连接,释放资源。
sql每个部分的执行顺序
-
FROM子句:选择表,将多个表进行CROSS JOIN(笛卡尔积),生成临时表。
-
ON:应用ON过滤器,执行表的联接条件。
-
JOIN:如果指定了OUTER JOIN(如LEFT OUTER JOIN、RIGHT OUTER JOIN),那么在应用ON过滤器之后,还会添加额外的行,并用NULL填充左表或右表的列。
-
WHERE子句:应用WHERE过滤器,删除不满足条件的行。
-
GROUP BY子句:根据指定的列分组结果集合中的行。
-
HAVING子句:应用HAVING过滤器,删除不满足条件的分组。
-
SELECT子句:选择特定的列。
-
DISTINCT子句:去除重复数据。
-
ORDER BY子句:根据指定的列对结果集进行排序。
-
LIMIT子句:限制结果集的数量
sql优化
- 合理设计数据库结构 数据库三范式,也要注意业务情况适当冗余。
- 合理使用索引 where 查询条件必要索引添加,注意索引添加规范,唯一性等
- 优化查询语句 见下文查询语句优化
- 适当分页 精确定位数据,避免无效数据影响
- 优化连接操作 数据库连接优化
- 监控和调优数据库设置 使用 MySQL 自带的性能监控工具(如 Performance Schema 和 sys schema) 使用第三方的性能监控工具,如 Percona Toolkit、pt-query-digest
查询语句优化
- 使用合适的查询语句,避免使用 SELECT *,只选择需要的字段。
- 尽量避免在 WHERE 子句中使用函数,函数会导致索引失效。
- 避免使用大量的子查询,可以通过 JOIN 操作替代。
- 合理使用 UNION、UNION ALL,避免不必要的排序和去重操作。
- 根据执行计划做出调整,使用 EXPLAIN
如索引建立是否符合要求,查看查询语句是否走索引,以及影响行数,是否可以提前先锁定确认需要的数据,避免无效数据影响效率等等
PS1:索引type有哪些类型以及意义?
-
ALL:全表扫描,MySQL 将遍历整张表来找到匹配的行。这通常是最低效的索引类型,尤其是当表较大时。
-
index:索引扫描,MySQL 将遍历索引树来查找匹配的行。这种情况下,MySQL 不需要扫描整张表,但是还是需要遍历索引树。
-
range:范围扫描,MySQL 使用索引来执行范围条件查询,例如使用 WHERE 子句中的 <、<=、>、>= 等操作符。
-
ref:基于索引的连接,MySQL 使用某个索引来从一个表中选择行,然后使用找到的键值来查找另一个表中的行。
-
eq_ref:唯一索引扫描,对于每个索引键,表中只有一条匹配的记录。这种类型通常出现在多表连接时,连接的字段有唯一索引。
-
const:常量查询,MySQL 在查询中找到了一个常数值,优化器将在查询执行之前将其转换为常量。
-
system:系统表,这是一个特殊的索引类型,它只包含一行或零行的表。这是 MySQL 内部使用的索引类型,不是常见的用户表索引类型。
-
NULL:没有使用索引。这意味着 MySQL 在查询执行过程中没有使用任何索引。
P:2:大量使用子查询会导致什么后果?
-
性能问题:每个子查询都需要单独执行,增加了数据库的负载。如果子查询嵌套层次较深或者数据量较大,可能导致查询时间过长,影响整体性能。
-
资源占用:每个子查询都需要占用数据库连接、内存和CPU等资源。当并发查询较多时,会增加数据库服务器的资源消耗,可能导致资源不足或者系统崩溃。
-
难以维护:大量的子查询会导致 SQL 语句复杂度增加,难以理解和维护。特别是当子查询嵌套层次较深时,SQL 语句变得更加晦涩难懂,增加了开发人员的工作量。
-
索引失效:某些情况下,子查询中的条件无法使用索引,导致全表扫描,进而影响查询性能。
-
可读性差:大量的子查询会使 SQL 语句变得冗长,可读性差,不利于其他开发人员理解和维护。
为了解决这些问题,可以考虑以下优化方法:
- 将部分子查询转换为 JOIN 操作,以减少嵌套查询的层数。
- 使用临时表或者视图来优化复杂的子查询结构。
- 对于特定的业务需求,可以考虑将复杂查询拆分为多个简单查询,并通过程序逻辑进行组合。
- 对查询语句进行分析和优化,尽量减少不必要的子查询,提高查询效率。
- 合理设计数据库结构和索引,以提高查询性能和效率。