【MySQL系列6】详解一条查询select语句和一条更新update语句的执行流程

本文详细解析了MySQL查询语句(select)和更新语句(update)的执行流程,涉及优化器的工作原理、查询计划的选择、优化策略以及存储引擎的交互。优化器根据统计信息选择执行计划,但并非总能选出最优方案。通过(optimizer_trace)可以观察优化过程。更新语句执行包括查询数据、使用Buffer Pool和redo log保证数据一致性,以及bin log确保事务安全性。理解这些流程有助于提高SQL性能和数据库管理。
摘要由CSDN通过智能技术生成

这个结果是通过一系列复杂的运算得到的,包括每个表或者索引的页面个数,索引的基数,索引和数据行的长度,索引分布的情况。

优化器在评估成本的时候,不会考虑任何缓存的作用,而是假设读取任何数据都需要经过一次IO操作。

优化器可以做哪些优化

优化器可以替我们做很多优化,下面列举一些常用的优化:

  • 重新定义关联的顺序。优化器并不一定按照我们写的查询关联语句中的关联顺序,而是会按照优化后的顺序进行查询。

  • 将外连接转为为内连接。

  • 使用等价转换原则。比如a<b and a=5会被转换为a=5 and b>5

  • 优化COUNT(),MIN()和MAX()

  • 预估并转化为常数表达式

  • 覆盖索引扫描。想要详细了解覆盖索引的可以点击这里

  • 子查询优化。

  • 提前终止查询。比如我们使用了一个不成立的条件,则会立刻返回空。

  • 等值传播。

  • 优化IN()语句。在其他很多数据库中in等同于or语句,但是MySQL中会讲in中的值先进行排序,然后按照二分查找的方法来确定是否满足条件。

实际当中优化器能做的优化远远比上面列举的更多,所以有时候我们不要觉得比优化器更聪明,所以大部分情况下我们都可以让优化器做出优化就可以了,如果有些我们确定优化器没有选择最优的查询方案,我们也可以在查询中通过添加hint提示告知到优化器,比如通过force index强制使用索引或者straight_join语句强制优化器按我们想要的表顺序进行关联。

优化器并不是万能的

MySQL优化器也并不是万能的,并不是总能把我们写的糟糕的sql语句优化成一个高效的查询语句,而且也有很多种原因会导致优化器做出错误的选择:

  • 统计信息不准确。MySQL评估成本依赖于存储引擎提供的的统计信息,然而存储引擎提供的统计信息有时候会有较大偏差。

  • 执行计划的成本估算不等于实际的执行成本。比如估算成本的时候不考虑缓存,而实际执行有些数据在缓存中。

  • 优化器认为的最优可能并不是我们需要的最优。比如有时候我们想要时间最短,但是优化器

  • 优化器从不考虑其他并发的查询。

  • 优化器并不总是基本成本的优化。有时候也会基于规则,比如当存在全文索引,查询时使用了match()子句时,即使选择其他索引更优,优化器仍然会选择全文索引。

  • 优化器不将不受其控制的操作计算为成本。如执行存储过程或者用户自定义函数的成本。

  • 优化器有时候无法估算所有的执行计划,所以也有可能错过最优执行计划。

优化器如何得到查询计划

优化器听起来比较抽象,给人一种看不见摸不着的感觉,但是实际上我们也可以通过参数打开优化器追踪,优化器追踪默认是关闭的,因为开启后会影响性能,所以建议是在需要定位问题的时候开启,并及时关闭。

SHOW VARIABLES LIKE ‘optimizer_trace’;

set optimizer_trace=‘enabled=on’;

接下来执行一句查询语句:

SELECT t1.nam

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL查询是指在一个查询中嵌套另一个查询,内部查询的结果作为外部查询的条件之一。MySQL查询可以用于SELECTUPDATE、DELETE语句中,可以帮助我们更好地处理复杂的数据查询和操作。 MySQL查询可以分为单行子查询和多行子查询两种类型。单行子查询返回的结果只有一行一列,多行子查询返回的结果有多行多列。 以下是MySQL查询的一些常见用法和示例: 1. 单行子查询 单行子查询返回的结果只有一行一列,可以用于比较操作符、HAVING子句、CASE语句等场景。 比较操作符示例: ```sql SELECT * FROM table1 WHERE column1 = (SELECT column2 FROM table2 WHERE column3 = 'value'); ``` HAVING子句示例: ```sql SELECT column1, COUNT(*) FROM table1 GROUP BY column1 HAVING COUNT(*) > (SELECT COUNT(*) FROM table2); ``` CASE语句示例: ```sql SELECT column1, column2, CASE WHEN column3 = (SELECT MAX(column3) FROM table2) THEN 'max' ELSE 'not max' END FROM table1; ``` 2. 多行子查询 多行子查询返回的结果有多行多列,可以用于比较操作符、相关子查询、相关更新、相关删除等场景。 比较操作符示例: ```sql SELECT * FROM table1 WHERE (column1, column2) IN (SELECT column1, column2 FROM table2 WHERE column3 = 'value'); ``` 相关子查询示例: ```sql SELECT * FROM table1 WHERE column1 IN (SELECT column1 FROM table2 WHERE column2 = 'value'); ``` 相关更新示例: ```sql UPDATE table1 SET column1 = 'new value' WHERE column2 IN (SELECT column2 FROM table2 WHERE column3 = 'value'); ``` 相关删除示例: ```sql DELETE FROM table1 WHERE column1 IN (SELECT column1 FROM table2 WHERE column2 = 'value');```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值