update更新很慢(字段类型引发)

 

 

     

开发人员在sql审核平台提交了2000多条update语句,每条语句只更新一条,where条件由索引,在sql审核平台在测试执行阶段已经执行了20多分钟。于是让看一下数据库后台线程是不是还在跑。

于是进入到mysql中执行:

mysql> pager grep -v Sleep;

mysql> show processlist;

发现还在跑,下面是经过处理的sql:

UPDATE port SET name = 'xxx', tel = '121212121212' WHERE order_id = 052001;

因为该服务器只用来测试阶段使用(就是先在该服务器执行一遍然后回滚,没问题后再去主库执行),所以机器性能并不是很好,如是看了一下IO情况:

clipboard.png发现一直是打满的情况,并且iowait也存在,于是开始就怀疑了是IO的问题,于是让开发将2000条sql,先提交100条看看,100条还是很慢,但是其他工单(测试用的同一个服务器)就比较快,于是感觉想的方向不对,开始查看表结构,果然看到了问题:

mysql> select count(*) from port;

大概300w条数据。

mysql> show create table port;

`order_id` varchar(20) NOT NULL DEFAULT '' COMMENT '订单ID'

该条件字段类型为varchar,而update的时候用的是int,没有加引号,所以引发了隐式类型转换,导致不能走索引,进而全表扫描,执行一条大概7s,2000*7/60≈3小时,对于2000条数据是一个比较庞大的一个时间呀!!!

根据官方文档的描述:

clipboard1.png简单解释一下就是:

① 如果比较操作中的两个参数都是字符串,则将它们作为字符串进行比较。

② 如果两个参数都是整数,则将它们作为整数进行比较。

③ 如果其中一个参数是TIMESTAMP或DATETIME列,而另一个参数是常量,则在执行比较之前将常量转换为时间戳。

④在所有其他情况下,参数都作为浮点数(双精度)进行比较。例如,字符串和数字操作数的比较会以浮点数的比较方式进行。

重要的是第④点,我们这里就是因为这个导致的,都进行了隐式转换不能走索引,导致全表扫。

 

最后,在设计表结构的时候,也要特别注意,要知道以后业务中该字段需要存储什么和使用什么类型的内容,再有查询和修改的时候要确认一下条件的字段类型。

 

posted on 2022-05-27 16:16  李努力ly  阅读(1082)  评论(0编辑  收藏  举报

导航