MySQL使用过程中的一些坑
pupuk opened this issue · comments
路漫漫其修远兮
Records
字段设计成字符串(如:char,varchar),查询是使用 数字,导致查询结果不准确或索引失效
如下,有一张表order订单表
mysql> desc order;
+-----------------------+------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+------------------------+------+-----+---------+----------------+
| order_id | int(11) | NO | PRI | NULL | auto_increment |
| order_sn | varchar(20) | NO | MUL | NULL | |
+-----------------------+------------------------+------+-----+---------+----------------+
order_sn上有一索引。
使用SQL语句:
SELECT order_id, order_sn FROM
my_order WHERE order_sn = '20180105160500862725';
如果order_sn
的值是20180105160500862725
,就会导致查询结果多了。
mysql> SELECT order_id, order_sn FROM `my_order` WHERE order_sn = '20180105160500862725';
+----------+----------------------+
| order_id | order_sn |
+----------+----------------------+
| 3827 | 20180105160500862725 |
+----------+----------------------+
1 row in set
mysql> SELECT order_id, order_sn FROM `my_order` WHERE order_sn = 20180105160500862725;
+----------+----------------------+
| order_id | order_sn |
+----------+----------------------+
| 3671 | 20180105160500861022 |
| 3553 | 20180105160500862149 |
| 3827 | 20180105160500862725 |
| 3786 | 20180105160500863824 |
| 3493 | 20180105160500864895 |
+----------+----------------------+
5 rows in set
查询结果不准确
当等号两边的值是不同类型时,MySQL会做隐式的类型转换。上面第二条MySQL语句,会做一个
F(String) = Number的操作,F是把String转成Number,然后与Number比较
mysql> SELECT '20180105160500861022' = 20180105160500862725 AS result;
+--------+
| result |
+--------+
| 1 |
+--------+
MySQL的隐式类型转换,网上资料很多,在此也不赘述,官方文档还是写的很详细的
https://dev.mysql.com/doc/refman/8.0/en/type-conversion.html
索引失效
也是同样的原因:
For comparisons of a string column with a number, MySQL cannot use an index on the column to look up the value quickly. If str_col is an indexed string column, the index cannot be used when performing the lookup in the following statement:
SELECT * FROM tbl_name WHERE str_col=1;
The reason for this is that there are many different strings that may convert to the value 1, such as '1', ' 1', or '1a'.
如果str_col是被索引的字符串列,当用数字number来查询比较时,不能用索引,是因为很多可能的字符串都能转换成相同的数值,MySQL显然不可能,列出这些可能的、有限的字符串。
要避免这个问题:
1、可以使用int的字段,尽量用int,不用char或者varchar,一是可以节省字节数,节省存储空间。二是也可以避免如上的错误,三是int类型的比较计算在微观上还是比char省资源。
2、应用程序框架,对所有字段的值都加上引号
如:SELECT * FROM
orderWHERE
col = 'value';
不管col列是int,还是char,varchar类型
如果col列是int,MySQL在查询的时候,也会把value从string转成int。