MySql :优化总结一

1. 对索引字段使用了函数,那么查询时,会走该索引的全表扫描。

由于加了 month() 函数操作,MySQL 无法再使用索引快速定位功能,而只能使用全索引扫描。

如下:
select count(*) from tradelog where month(t_modified)=7; //查询表中所有年份的7月份纪录个数。

其中的 month()是函数,假设表中只有 21,22年和23年的数据,那么改进的SQL如下:
mysql> select count(*) from tradelog where
(t_modified >= ‘2021-7-1’ and t_modified<‘2021-8-1’) or
(t_modified >= ‘2022-7-1’ and t_modified<‘2022-8-1’) or
(t_modified >= ‘2023-7-1’ and t_modified<‘2023-8-1’);

2. 隐式使用函数,如下:

select * from tradelog t where t.tradid = 110717; //其中的 tradid 类型为 varchar2(32);

MySQL 规定当 ‘字符串’和 ‘整型’比较的时候,会把 ‘字符串’类型先转化为‘整型’。

所以上面的语句就相当于:

mysql> select * from tradelog where CAST(tradid AS signed int) = 110717;

也就是说,这条语句触发了我们上面说到的规则:对索引字段做函数操作,优化器会放弃走树搜索功能。

下面这条查询语句会导致走全局扫描吗?

select * from tradelog where id = “83126”; // 其中 id 是 整型的

答案是不会的,为啥呢?因为上面说过了,当 ‘字符串’和 ‘整型’比较的时候,会把 ‘字符串’类型先转化为‘整型’,

所以上面的语句相当于:

mysql> select * from tradelog where id = CAST(‘110717’ AS signed int);

没有对索引字段 id 进行函数操作,所以不会走全局扫描。

-------------------------------------------------- MySQL 行锁 -------------------------------------------------------------
在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。这个就是两阶段锁协议。

产生幻读的原因是,行锁只能锁住行,但是新插入记录这个动作,要更新的是记录之间的“间隙”。
因此,为了解决幻读问题,InnoDB 只好引入新的锁,也就是间隙锁 (Gap Lock)。

间隙锁和行锁合称 next-key lock,每个 next-key lock 是前开后闭区间。

如果没有特别说明,我们把间隙锁记为开区间,把 next-key lock 记为前开后闭区间。

注意,间隙锁是在可重复读隔离级别下才会生效的。所以,你如果把隔离级别设置为读提交的话,就没有间隙锁了。

我总结的加锁规则里面,包含了两个“原则”、两个“优化”和一个“bug”。

原则 1:加锁的基本单位是 next-key lock。希望你还记得,next-key lock 是前开后闭区间。

原则 2:查找过程中访问到的对象才会加锁。

优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。

优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。

一个 bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值