暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL tips(十一)——SQL执行慢

爱可可的人生记录仪 2020-01-09
277

在 MySQL 中,有很多看上去逻辑相同,但性能却差异巨大的 SQL 语句。

条件字段函数操作

如果对字段做了函数计算,就用不上索引了,这是 MySQL 的规定。

对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能。

比如,对于 select * from tradelog where id + 1 = 10000 这个 SQL 语句,这个加 1 操作并不会改变有序性,但是 MySQL 优化器还是不能用 id 索引快速定位到 9999 这一行。所以,需要你在写 SQL 语句的时候,手动改写成 where id = 10000 -1 才可以。


隐式类型转换

比如select * from tradelog where tradeid=1;但tradeid 的字段类型是 varchar(32)。在 MySQL 中,字符串和数字做比较的话,是将字符串转换成数字。所以这个语句就相当于select * from tradelog where  CAST(tradid AS signed int) = 1;触发了我们上面说到的规则:对索引字段做函数操作,优化器会放弃走树搜索功能。


隐式字符编码转换

如果两个表的字符集不同,一个是 utf8,一个是 utf8mb4,做表连接查询的时候用不上关联字段的索引。字符集 utf8mb4 是 utf8 的超集,所以当这两个类型的字符串在做比较的时候,MySQL 内部的操作是,先把 utf8 字符串转成 utf8mb4 字符集,再做比较。字符集不同只是条件之一,连接过程中要求在被驱动表的索引字段上加函数操作,是直接导致对被驱动表做全表扫描的原因。


有些情况下,“查一行”,也会执行得特别慢,如果数据库压力本身就很大的情况不考虑。

第一类:查询长时间不返回

一般碰到这种情况的话,大概率是表 t 被锁住了。接下来分析原因的时候,一般都是首先执行一下 show processlist 命令,看看当前语句处于什么状态。

1.等 MDL 锁

state:Waiting for table metadata lock,这个状态表示的是,现在有一个线程正在表 t 上请求或者持有 MDL 写锁,把 select 语句堵住了。可以通过查询sys.schema_table_lock_waits 这张表,我们就可以直接找出造成阻塞的 process id,把这个连接用 kill 命令断开即可。

2.等 flush

state: Waiting for table flush, 出现这种状态的可能情况是:有一个 flush tables 命令被别的语句堵住了,然后它又堵住了我们的 select 语句。基本上show proccesslist看结果就知道了。

3.等行锁

state:statistics 存在写锁,MySQL 5.7 版本,可以通过 sys.innodb_lock_waits 表查到。

select * from t sys.innodb_lock_waits where locked_table=tablename;


第二类:查询慢

数据量大,做了全表扫描。有一致性读的问题存在,执行过程中可能存在大量DML。


参考资料:丁奇,MySQL实战45讲



部分内容来自网络,如有侵权请联系作者删除。



文章转载自爱可可的人生记录仪,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论