mysql5.7 隐士转换

155 阅读3分钟

前言:主要内容概括

  • mysql 字符串与数字转化的数值
  • mysql 隐士转换发生的情况以及解决办法
  • mysql null值对性能的影响

一: 字符串和数字的比较情况

mysql对于字符串和数字的比较存在隐士转换,默认字符串转换成为数字
  默认 字符串会默认转化成为数字,并且从左右到又开始转换成为具体数值,直到不符合要求
  ps: 结果为1则表示true 结果为0则表示false
  MySQL [(none)]> select "avc" = 0;
+-----------+
| "avc" = 0 |
+-----------+
|         1 |
+-----------+
1 row in set (0.00 sec)

MySQL [(none)]> select "avc" = 1;
+-----------+
| "avc" = 1 |
+-----------+
|         0 |
+-----------+
1 row in set (0.00 sec)
  以上说明 'avc' 转换成为了0 
  
MySQL [(none)]> select "1avc" = 1;
+------------+
| "1avc" = 1 |
+------------+
|          1 |
+------------+
1 row in set (0.00 sec)

MySQL [(none)]> select "01avc" = 1;
+-------------+
| "01avc" = 1 |
+-------------+
|           1 |
+-------------+
1 row in set (0.00 sec)

MySQL [(none)]> select "010avc" = 1;
+--------------+
| "010avc" = 1 |
+--------------+
|            0 |
+--------------+
1 row in set (0.00 sec)
  以上说明: '1avc' 取到1读取到a则结束,转化成为1
           '01avc' 读取到01读取到a则结束,01 转化成为1
           '010avc' 度渠道010度去到a结束,010 转化为10
 

二: mysql 隐士转换发生的情况以及解决办法

1 数据类型不一致会造成隐士转换
  比如: 字段类型为varchar,但是传入的数据为int则有可能不能正确使用索引
  select * from tableName where tableId = 110717;
  虽然能查出具体的数据,但是查看执行计划,可以发现未使用索引
  实际执行的sql会被内部转化为:
    select * from tableName where CAST(tableId AS signed int) = 110717;
2 字符集不一致
  通常情况下这种情况在mysql内部join才会发生这种情况,代码传入变量的方式很少发生这个问题
  相当于执行结果sql:
    select * from tableName where CONVERT(tableName USING utf8mb4)="xxxx";
隐士转化的原因:
  mysql使用的是B+树算法,树状结构保证了数据有序性,并且实现类似于二分查找的查找方法,方便快速定位和范围查询,至于隐士转化不能完成索引使用的原因: 破坏了索引树的有序性,放弃执行索引导致
  比如:   select * from tableName where tableId = 110717; 如果tableId 存在索引情况.
  正常执行逻辑:
    通过tableId的二级索引树,快速查找到具体数据,获取到聚簇索引的主键Id,然后变成主表的命中查询
  隐士转化执行逻辑:
    每次执行的时候,树的数据进行类型转换,则树不能继续保持有序性,所以执行查找只能通过主键全表扫描进行判断.
    
隐士转化的常规优化措施:
  1 对于实际执行的sql,如果传入的字段类型不匹配,则通常优化程序,在传入的时候直接传入正确的类型
  2 如果是一些BI情况下的sql,由于数据库字段定义情况造成表相同字段类型不一致,但是需要做关联条件
    则需要开发人员根据情况判断,如果存在主表,大小表问题,则可以手动选择转换那个字段实现先转换,拿到数据之后让从表达到实现索引的目的
  3 但是实际运行过成功,不用记住所用,只需要居住规则。然后熟练使用explain sql... 去去查看执行计划 + force 具体执行查看那个索引更优,那种方案更能使用到索引.   

三: null值对性能的影响

1 额外存储null,需要更多空间
2 索引失效
    原因: 单列不存储null值,多列不存储全为null的数值(所以 is null 无法使用索引) 
3 null 只能用is null/is not null进行判断