MySQL隐式转换测试

2022-11-10,,,

 
Preface
 
    There're various data type in MySQL such as number,string,date,time,lob,etc.The data type will convert implicitly if we don't use a proper operand in a SQL statement which may even contain expressions.These implicit conversion of data type sometimes may lead to performance issues because it will make the indexes on the very columns be useless.We should do our best to avoid implicit conversion in our product environment by explicitly specifying the same data type with the relevant column.
    The principle of implicit conversion in MySQL is to make the operation be as compatible as possible and not return result(In most cases,it may be wrong).Athough we can use cast() and convert() function to convert the data type,but it's better to speicify correct data type directly on account of consideration of performance.Notice that you'de better always keep functions in the right side.
 

Example
 
Test the implicit conversion in function convert() and cast().

 (zlm@192.168.1.101 )[zlm]>select cast('2abc' as unsigned) from dual;
+--------------------------+
| cast('2abc' as unsigned) |
+--------------------------+
| |
+--------------------------+
row in set, warning (0.00 sec) (zlm@192.168.1.101 )[zlm]>select convert('2abc',unsigned) from dual;
+--------------------------+
| convert('2abc',unsigned) |
+--------------------------+
| |
+--------------------------+
row in set, warning (0.00 sec) //Function cast() and convert() turned the string '2abc' to number.
//The result became 2 what means the string begin with number only keep the first number remain. (zlm@192.168.1.101 )[zlm]>select convert('abc',unsigned) from dual;
+-------------------------+
| convert('abc',unsigned) |
+-------------------------+
| |
+-------------------------+
row in set, warning (0.00 sec) (zlm@192.168.1.101 )[zlm]>select cast('abc' as unsigned) from dual;
+-------------------------+
| cast('abc' as unsigned) |
+-------------------------+
| |
+-------------------------+
row in set, warning (0.00 sec) //If there's no number prefix,the result turns out to be zero(integer type here). (zlm@192.168.1.101 )[zlm]>select ''=convert('3abc',unsigned);
+-----------------------------+
| ''=convert('abc',unsigned) |
+-----------------------------+
| |
+-----------------------------+
row in set, warning (0.00 sec) (zlm@192.168.1.101 )[zlm]>select ''=cast('3abc' as unsigned);
+-----------------------------+
| ''=cast('abc' as unsigned) |
+-----------------------------+
| |
+-----------------------------+
row in set, warning (0.00 sec) (zlm@192.168.1.101 )[zlm]>select =convert('3abc',unsigned);
+-----------------------------+
| ''=convert('abc',unsigned) |
+-----------------------------+
| |
+-----------------------------+
row in set, warning (0.00 sec) (zlm@192.168.1.101 )[zlm]>select =cast('3abc' as unsigned);
+-----------------------------+
| ''=cast('abc' as unsigned) |
+-----------------------------+
| |
+-----------------------------+
row in set, warning (0.00 sec) //All the rusults are 1 what means the implicit conversion occurs.

Test the implicit conversion in expression and function concat().

 (zlm@192.168.1.101 )[zlm]>select +'abc' from dual;
+----------+
| +'abc' |
+----------+
| |
+----------+
row in set, warning (0.01 sec) //The string 'abc' converted implicitly from string to number and got result of 10(10 + 0 = 0). (zlm@192.168.1.101 )[zlm]>select concat(,'abc') from dual;
+------------------+
| concat(,'abc') |
+------------------+
| 10abc |
+------------------+
row in set (0.00 sec) //The number 10 was converted implicitly to string and concantenated by string 'abc'. (zlm@192.168.1.101 )[zlm]>select +'abc'=concat(,'abc');
+---------------------------+
| +'abc'=concat(,'abc') |
+---------------------------+
| |
+---------------------------+
row in set, warning (0.00 sec) //What may astonish us is that the result became 1,that is,implicit conversion occured again. (zlm@192.168.1.101 )[zlm]>select =concat(,'abc')-'abc';
+---------------------------+
| =concat(,'abc')-'abc' |
+---------------------------+
| |
+---------------------------+
row in set, warning (0.00 sec) //Moving the string 'abc' to the right side didn't influence the result of 1.

Test the implicit conversion in table.

 (zlm@192.168.1.101 )[sysbench]>desc sbtest1;
+-------+-----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+---------+----------------+
| id | int() | NO | PRI | NULL | auto_increment |
| k | int() | NO | MUL | | |
| c | char() | NO | | | |
| pad | char() | NO | | | |
+-------+-----------+------+-----+---------+----------------+
rows in set (0.00 sec) (zlm@192.168.1.101 )[sysbench]>select * from sbtest1 limit ;
+----+------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
| id | k | c | pad |
+----+------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
| | | --------- | ---- |
| | | --------- | ---- |
| | | --------- | ---- |
| | | --------- | ---- |
| | | --------- | ---- |
+----+------+-------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------+
rows in set (0.00 sec) (zlm@192.168.1.101 )[sysbench]>explain select * from sbtest1 where id='';
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| | SIMPLE | sbtest1 | NULL | const | PRIMARY | PRIMARY | | const | | 100.00 | NULL |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
row in set, warning (0.00 sec) (zlm@192.168.1.101 )[sysbench]>explain select * from sbtest1 where id=cast( as char);
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| | SIMPLE | sbtest1 | NULL | const | PRIMARY | PRIMARY | | const | | 100.00 | NULL |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
row in set, warning (0.00 sec) //Despite I've specified 1 as string above,the queries still return result with primary key. (zlm@192.168.1.101 )[sysbench]>alter table sbtest1 add unique(c); //Add a unique key on column c(char type).
Query OK, rows affected ( min 58.75 sec) //It cost almost 5 mins.
Records: Duplicates: Warnings: (zlm@192.168.1.101 )[sysbench]>desc sbtest1;
+-------+-----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+---------+----------------+
| id | int() | NO | PRI | NULL | auto_increment |
| k | int() | NO | MUL | | |
| c | char() | NO | UNI | | |
| pad | char() | NO | | | |
+-------+-----------+------+-----+---------+----------------+
rows in set (0.00 sec) (zlm@192.168.1.101 )[sysbench]>select count(*) from sbtest1;
+----------+
| count(*) |
+----------+
| |
+----------+
row in set (3.52 sec) //Query 1
(zlm@192.168.1.101 )[sysbench]>explain select * from sbtest1 where c=---------;
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| | SIMPLE | sbtest1 | NULL | ALL | c | NULL | NULL | NULL | | 10.00 | Using where |
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
row in set, warnings (0.00 sec) //Query 2
(zlm@192.168.1.101 )[sysbench]>explain select * from sbtest1 where c='83868641912-28773972837-60736120486-75162659906-27563526494-20381887404-41576422241-93426793964-56405065102-33518432330';
+----+-------------+---------+------------+-------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+------+---------+-------+------+----------+-------+
| | SIMPLE | sbtest1 | NULL | const | c | c | | const | | 100.00 | NULL |
+----+-------------+---------+------------+-------+---------------+------+---------+-------+------+----------+-------+
row in set, warning (0.01 sec) //Query 3
(zlm@192.168.1.101 )[sysbench]>explain select * from sbtest1 where c like ;
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| | SIMPLE | sbtest1 | NULL | ALL | c | NULL | NULL | NULL | | 11.11 | Using where |
+----+-------------+---------+------------+------+---------------+------+---------+------+---------+----------+-------------+
row in set, warnings (0.00 sec) //Query 4
(zlm@192.168.1.101 )[sysbench]>explain select * from sbtest1 where c like '83868641912%';
+----+-------------+---------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+
| | SIMPLE | sbtest1 | NULL | range | c | c | | NULL | | 100.00 | Using index condition |
+----+-------------+---------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+
row in set, warning (0.00 sec) //The implicit conversion occured in query 1 and query 3.They cannot use the index on column c.
//In query 4,it even used ICP feature of MySQL(Which is supported since version 5.6).

Summary

The implicit conversion usually occurs to make the query to be as compatible as possible in MySQL.
The implicit conversion occurs in expression,function and condiction of queries.
The implicit conversion may lead to bad performance because it will prevent MySQL from using indexes on specific query columns.
We'd better specify the correct data type explicit when typing them in our query SQL statement to avoid the implicit conversion.

MySQL隐式转换测试的相关教程结束。

《MySQL隐式转换测试.doc》

下载本文的Word格式文档,以方便收藏与打印。