MySQL 常见性能问题

MySQL 常见性能问题:

一、条件字段函数操作:

  1. 如果对字段做了函数计算,该字段就用不上索引了;
  2. 对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能

注意

  • 优化器并不是要放弃使用这个索引,而是放弃了树搜索功能,优化器可以选择遍历主键索引,也可以选择遍历二级索引,只是遍历二级索引的时,会导致全表扫描,根本起不到索引的作用

二、隐式类型转换:

若表中tradeid字段上,建立了索引,数据类型是varchar(32)类型,而你执行语句,会发现会走全表扫描,因为你输入的参数是整型,所以需做类型转换

select * from table where tradeid=12345;

对于优化器来说,上述语句相当于:

select * from table where CAST(tradid AS signed int ) = 12345;
  • 简单说:对索引字段做了函数操作,优化器会放弃走树搜索功能

1.数据类型转换的规则怎么使用?

看select “10” > 9 的结果:

mysql> select 10 >"9";

+---------+
| 10 >"9" |
+---------+
|       1 |
+---------+
  1. 若规则是"将字符串转成数字",那么就是做数字比较,结果是1;
  2. 若规则是"将数字转成字符串",那么就是做字符串比较,结果是0;
  3. select “10” > 9 返回的是1,所以能确认MySQL里转换规则了,在MySQL中,字符串和数字做比较的话,是将字符串转换成数字;

总结:在MySQL中,字符串和数字做比较的话,是将字符串转换成数字;

三、隐式字符编码转换:

  1. 做表连接查询的时候,两个表的字符集要是不同,会导致表连接查询的时候用不上关联字段的索引;
  2. 连接过程中要求在被驱动表的索引字段上加函数操作,是直接导致对被驱动表做全表扫描的原因;

1.为什么字符集不同就用不上索引呢?

当字符集是utf8mb4是utf8的超集,所以当两个类型的字符串在做比较时,MySQL内部的操作是,先把utf8字符串转成utf8mb4字符集,再做比较;

因此在执行语句时,需要将被驱动数据表里的字段一个个地转换成utf8mb4,在进行做比较

select * from table where CONVERT(traideid USING utf8mb4) = $L2.tradeid.value;

CONVERT()函数,在这里就是把输入的字符串转换成utf8mb4字符集

再次触发,对索引字段做函数操作,优化器会放弃走树搜索功能;

总结

  1. 如果驱动表的字符集比被驱动表的字符集小,关联列就能用到索引,如果更大,需要发生隐式编码转换,则不能使用索引;
  2. latin < gbk < utf8 < utf8mb4

四、为什么查一句语句,执行也是很慢?

第一种原因

MySQL数据库本身被堵住,比如:系统或网络资源不够;

数据库本身就有很大压力,导致数据库服务器CPU占有率很高或IO利用率很高

第二种原因

SQL语句被堵住,比如:表锁,行锁等,导致存储引擎不同执行的对于SQL语句;

  • 使用show processlist, 查看当前所有的执行进程;

  • 使用查询sys.cahema_table_lock_waits 找出造成阻塞的process id,把这个连接用kill命令断开;

    select blocking_pid from sys.schema_table_lock_waits;

  • 若有线程正要对表t做flush操作:

    flush tables t with read lock; 仅关闭表t

    flush tables with read lock; 关闭所有打开的表

  • 查看谁占的写锁(版本:5.7),可通过sys.innodb_lock_waits;

    select * from sys.innodb_lock_waits where locked_table = '`库名`.`表名`';\G
    

第三种原因

索引使用不当,上述的说明;

第四种原因

表中数据的特点导致,走了索引,但回表次数庞大;

  • 比如定义字段b的数据类型varchar(10),执行SQL语句:

    select * from table where b='1234567890abcd'
    1. 在传给引擎执行的时,做了字符截断。因为引擎里这个行只定义了长度10,所以只截了前10个字节,就是"123456789"进去匹配;
    2. 若满足条件数据,b字段’123456789’有10万行数据;
    3. 因为是select * ,所以要做10万次回表;
    4. 但是每次回表以后查出整行,到server层判断,b的值都不是"1234567890abcd";
    5. 返回结果是空;
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值