在多数时候我们都会对数据库建立索引,然后在书写SQL语句的时候尽可能的用上索引中所使用的字段,但是我们这样做后确实用到了这个索引了吗?事实是未必的,比如当SQL中Where条件值类型和字段定义的类型不一致时,这个索引就不会被用上。
定义如下表结构 CREATE TABLE peng_data (
phone varchar(21),
stat varchar(4),
KEY phonestat (stat, phone)
);
插入n多的数据后来做测试,首先查看插入的数据记录数。
SELECT count(*) FROM peng_data;
+----------+
| count(*) |
+----------+
| 5925 |
+----------+
1 row in set (1.85 sec)
我们写两个SQL,一个
SELECT SQL_NO_CACHE count(*) FROM peng_data WHERE stat = 0;
+----------+
| count(*) |
+----------+
| 3640 |
+----------+
1 row in set (0.05 sec)
再看另一个 SELECT SQL_NO_CACHE count(*) FROM peng_data WHERE stat = ‘0′;
+----------+
| count(*) |
+----------+
| 3566 |
+----------+
1 row in set (0.00 sec)
为什么前面一种写法执行所需要时间较长并且所选择出的记录数多一些呢?
我们 使用EXPLAIN看一下对索引的使用情况
EXPLAIN SELECT SQL_NO_CACHE count(*) FROM peng_data WHERE stat = 0;
+----+-------------+-----------+-------+---------------+-----------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+-----------+---------+------+------+--------------------------+
| 1 | SIMPLE | peng_data | index | phonestat | phonestat | 75 | NULL | 5925 | Using where; Using index |
+----+-------------+-----------+-------+---------------+-----------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
看rows 5925 实际进行了一次全表检索,索引没有利用上。
再看第二种
EXPLAIN SELECT SQL_NO_CACHE count(*) FROM peng_data WHERE stat = ‘0′;
+----+-------------+-----------+------+---------------+-----------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+-----------+---------+-------+------+--------------------------+
| 1 | SIMPLE | peng_data | ref | phonestat | phonestat | 12 | const | 2968 | Using where; Using index |
+----+-------------+-----------+------+---------------+-----------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)
为什么这么样呢,原因就在于所使用的条件的字段值类型和数据库的定义的字段类型不一样时,MySQL就会在内部做数据转化,他的处理行为就会和我们期望的有一些不一样,在这里当我们使用整数来作为定义中的字符串字段做比较时,MySQL会自动的将数据库中的记录转化为整数做比较,而且将空值转化为整数0做比较,所以选出来的记录数多一些。
由此得到当MySQL的Where值类型和数据库定义的字段类型不一致时会发生:
1. 建立的索引实际没有被使用上,导致查询效率低下。
2. 由于数据库对一些值的默认转化,导致查询的结果偏离实际的期望。
字段类型不一样,在进行比较时,用不上index是符合运算的列使用不了index。