今天在处理一个问题的时候,需要根据其他部门提供的sql语句对一个表中的数据进行了筛查。
语句类似下面的形式
> SELECT MAX_LEVEL,LOGOUT_TIME,CURRENT_DATE AS NOWTIME,cn_master FROM t_test_october_back_a WHERE ID in ( 100, 200, 300, 400, 500) ;
+-----------+---------------+------------+-----------+
| MAX_LEVEL | LOGOUT_TIME | NOWTIME | ID|
+-----------+---------------+------------+-----------+
| 1 | 1440407918000 | 2015-08-31 | 100|
| 100| 1441009281000 | 2015-08-31 | 200|
| 1 | 1440408002000 | 2015-08-31 | 300|
+-----------+---------------+------------+-----------+
x rows in set, 65535 warnings (10.98 sec)
本来这一个简单查询就完成了,也得到了业务部门需要的数据情况,但是查看最后一行的内容,还是有些蹊跷。如果观察仔细,对于这种id的数据查询,走索引的话,绝对不会再10秒左右,这是第一个奇怪的地方,第二个奇怪的地方就是65535 warnings,一个简单查询怎么会有这么多的warnings
最开始怕show warnings的时候会一下子显示出来6万多行数据,还小小担心了一下,结果输出的结果只有64行。
>show warnings;
+---------+------+----------------------------------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '[email protected]' |
| Warning | 1292 | Truncated incorrect DOUBLE value: '[email protected]' |
| Warning | 1292 | Truncated incorrect DOUBLE value: '[email protected]' |
| Warning | 1292 | Truncated incorrect DOUBLE value: '[email protected]' |
| Warning | 1292 | Truncated incorrect DOUBLE value: '[email protected]' |
...
64 rows in set (0.00 sec)
查看建表语句,发现这个id列是varchar类型的。
>show create table t_test_october_back_a;
| t_tl_october_back_a | CREATE TABLE `t_tl_october_back_a` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`id` varchar(60) NOT NULL,
`area_server` varchar(80) NOT NULL,
`max_level` tinyint(4) NOT NULL,
`logout_time` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_test_october_back_cn_master` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2042252493 DEFAULT CHARSET=gbk |
隐式转换,由字符转换为数字的时候,直接走了全表扫描
mysql> explain select *from test where id2=2;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | test | ALL | idx_id2 | NULL | NULL | NULL | 3 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
###############
Oracle 11gR2
sqlplus -v
SQL*Plus: Release 10.2.0.3.0 - Production
SQL> create table test (id1 number,id2 varchar2(10));
SQL> insert into test values(1,'1');
SQL> begin
2 for i in 1..100 loop
3 insert into test values(i,chr(39)||i||chr(39));
4 end loop;
5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
SQL> exec dbms_stats.gather_table_stats('TEST','TEST',CASCADE=>TRUE);
隐式转换,由数字转换为字符的时候,直接走了索引扫描
SQL> explain plan for select *from test where id1='2';
SQL> select *from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3847161316
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 7 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_ID1 | 1 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
2 - access("ID1"=2)
隐式转换,由字符转换为数字的时候,直接走了全表扫��
SQL> explain plan for select *from test where id2=3;
SQL> select *from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1357081020
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TEST | 1 | 7 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 - filter(TO_NUMBER("ID2")=3)
可见在这个方面MySQL和Oracle中的表现是一致的,对于这种隐式转换还是要多加注意。