1. 关于函数
mysql在大多数情况下,使用了函数是不走索引的,oracle倒是很多情况下都可以走索引(这就是好东西一分价钱一分货啊,比如联合索引,oracle在第一个列未命中索引的情况下,仍然可以命中第二个索引,因为oracle有跳跃式索引)
索引无法被利用:
某些函数会对列的值进行处理,这会导致索引无法被正确地利用。
例如,如果在索引列上使用了函数,MySQL将无法使用该索引来加速查询。
函数导致全表扫描:
当在查询条件中使用函数时,MySQL通常无法使用索引来加速查询,而会执行全表扫描。
这是因为函数的计算需要应用到每一行数据上,而无法直接在索引数据上进行。
函数可能降低查询性能:
某些函数的计算成本较高,会增加查询的执行时间。如果在查询中频繁使用这些函数,可能会导致查询性能下降。
为了避免函数对索引的影响,可以考虑以下几点:
尽量避免在索引列上使用函数,尽量使用原始列进行条件过滤。
如果需要对某个列进行函数处理,并且该列上有索引,可以考虑创建一个虚拟列(或计算列),
将函数处理的结果存储在虚拟列上,并为该虚拟列创建索引。
2. mysql在列上进行函数计算时无法走索引
如上图,已在时间字段加上索引,但是仍然无法命中索引,
情况如下图:
explain select * from xin_student_t where date(create_time) = '2022-11-06'
3. 优化sql走索引:
explain select * from xin_student_t where create_time>='2022-11-06'
and create_time < date_add('2022-11-06',INTERVAL 1 day);
4. 使用函数索引(mysql8.0版本及以上才支持)
msql5.7新增的虚拟列功能也是可以达到使用索引的。
MySQL8.0增加了函数索引,其实它也是依据虚拟列来实现的。
-
- 加索引
drop index index_xin_student_t_create_time on xin_student_t;
-- 下面这种写法会报错
alter table xin_student_t add index fun_index_xin_student_t_create_time(date(create_time));
-- 这种写法是正确的,可以看出上面少写了对括号
alter table xin_student_t add index fun_index_xin_student_t_create_time((date(create_time)));
-- 另一种正确写法
create index fun_index_xin_student_t_create_time on xin_student_t(((date(create_time))));
-
- 索引生效
explain select * from xin_student_t where date(create_time) = '2022-11-06'