一:条件字段函数操作:
mysql> CREATE TABLE `tradelog` (
`id` int(11) NOT NULL,
`tradeid` varchar(32) DEFAULT NULL,
`operator` int(11) DEFAULT NULL,
`t_modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `tradeid` (`tradeid`),
KEY `t_modified` (`t_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
mysql> select count(*) from tradelog where month(t_modified)=7;
如果是where t_modified='2018-7-1';就会像上图执行的逻辑。
实际上,b+数提供的这个快速定位能力,来源于同一层兄弟节点的有序性。
如果传入7树的第一层就不知道怎么办了。
对索引字段做函数操作,可能会破坏函数索引值的有序性,所以放弃走搜索树。
使用了t_modified这个索引,扫描了整个索引的所有值。
优化:mysql> select count(*) from tradelog where
-> (t_modified >= '2016-7-1' and t_modified<'2016-8-1') or
-> (t_modified >= '2017-7-1' and t_modified<'2017-8-1') or
-> (t_modified >= '2018-7-1' and t_modified<'2018-8-1');
二:隐式类型转换
mysql> select * from tradelog where tradeid=110717;
tradeid是varchar(32),这里是把字符串转化为了整数。
相当于
mysql> select * from tradelog where CAST(tradid AS signed int) = 110717;
三:隐式字符编码转换
mysql> CREATE TABLE `trade_detail` (
`id` int(11) NOT NULL,
`tradeid` varchar(32) DEFAULT NULL,
`trade_step` int(11) DEFAULT NULL, /* 操作步骤 */
`step_info` varchar(32) DEFAULT NULL, /* 步骤信息 */
PRIMARY KEY (`id`),
KEY `tradeid` (`tradeid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into tradelog values(1, 'aaaaaaaa', 1000, now());
insert into tradelog values(2, 'aaaaaaab', 1000, now());
insert into tradelog values(3, 'aaaaaaac', 1000, now());
insert into trade_detail values(1, 'aaaaaaaa', 1, 'add');
insert into trade_detail values(2, 'aaaaaaaa', 2, 'update');
insert into trade_detail values(3, 'aaaaaaaa', 3, 'commit');
insert into trade_detail values(4, 'aaaaaaab', 1, 'add');
insert into trade_detail values(5, 'aaaaaaab', 2, 'update');
insert into trade_detail values(6, 'aaaaaaab', 3, 'update again');
insert into trade_detail values(7, 'aaaaaaab', 4, 'commit');
insert into trade_detail values(8, 'aaaaaaac', 1, 'add');
insert into trade_detail values(9, 'aaaaaaac', 2, 'update');
insert into trade_detail values(10, 'aaaaaaac', 3, 'update again');
insert into trade_detail values(11, 'aaaaaaac', 4, 'commit');
mysql> select d.* from tradelog l, trade_detail d where d.tradeid=l.tradeid and l.id=2; /* 语句 Q1*/
1.在tradelog上使用了主键索引。
2.key=null 表示没有在详情表上使用索引。全表扫面
第三步的可以看做如下sql:
mysql> select * from trade_detail where tradeid=$L2.tradeid.value;
其中$L2.tradeid.value的字符集是utf8mb4;
等同于select * from trade_detail where CONVERT(traideid USING utf8mb4)=$L2.tradeid.value;
连接过程中要求在被动驱动表的索引字段上加函数操作。
看下面这个:
mysql>select l.operator from tradelog l , trade_detail d where d.tradeid=l.tradeid and d.id=4;
select operator from tradelog where traideid =$R4.tradeid.value;
select operator from tradelog where traideid =CONVERT($R4.tradeid.value USING utf8mb4);
这里的convert函数是加在输入参数上的。这样就可以用上被驱动表的traidid索引。
如果要优化
(1)alter table trade_detail modify tradeid varchar(32) CHARACTER SET utf8mb4 default null;
(2)mysql> select d.* from tradelog l , trade_detail d where d.tradeid=CONVERT(l.tradeid USING utf8) and l.id=2;