Mysql使用函数后不走索引怎么优化?

这篇具有很好参考价值的文章主要介绍了Mysql使用函数后不走索引怎么优化?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

网上很多人说mysql一旦使用函数就不走函数,但是事实真的是如此吗?我先说明,并不是如此的,本篇文章会通过DAYOFWEEK()substr()两个函数作为条件查询,看看究竟是否会走索引(其他函数同理),使用函数不走索引的时候又应该如何做sql优化,本篇文章重点是基于这两点进行分析。

一、什么场景下使用函数索引会失效?

测试数据如下:

create_time和name列是都建立了索引的。

DROP TABLE IF EXISTS `demo`;
CREATE TABLE `demo`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `create_time` datetime NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `create_time`(`create_time`) USING BTREE,
  INDEX `name`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;


INSERT INTO `demo` VALUES (1, '2023-04-28 10:41:16', 'zhangsan');
INSERT INTO `demo` VALUES (2, '2023-04-01 10:41:22', 'lisi');

DAYOFWEEK():函数返回日期的工作日索引值,即星期日为1,星期一为2,星期六为7。 这些索引值对应于ODBC标准。

通过下面会发现一个问题,假如是select * 的情况下是不会走索引的,假如是只返回使用函数的列是会走索引的。

EXPLAIN SELECT * from  demo WHERE dayofweek(create_time) = 6 \G;

EXPLAIN SELECT dayofweek(create_time),create_time from  demo WHERE dayofweek(create_time) = 6 \G;

Mysql使用函数后不走索引怎么优化?

关于执行计划的解读:

Mysql使用函数后不走索引怎么优化?

截取字符串语法:substr(obj,start,length)

参数:

  • obj:从哪个内容中截取,可以是数值或字符串。
  • start:从哪个字符开始截取(1开始,而不是0开始)
  • length:截取几个字符(空格也算一个字符)。

通过下面案例会发现,跟上面的案例是一样的,同样是select * 的情况下是不会走索引的。

EXPLAIN SELECT *  from demo WHERE substr(name,1,3) = 'lis'\G;

EXPLAIN SELECT substr(name,1,3),name,id  from demo WHERE substr(name,1,3) = 'lis'\G;

Mysql使用函数后不走索引怎么优化?

二、索引失效了应该怎么处理?

1.通过【sql优化】让索引生效

那么问题来了遇到这种查询所有数据使用函数不走索引的我们应该如何优化。通过以下试验发现可以携带id,id是主键的情况下不会导致索引失效!

EXPLAIN SELECT substr(name,1,3),name,id,create_time  from demo WHERE substr(name,1,3) = 'lis'\G;

EXPLAIN SELECT substr(name,1,3),name,id  from demo WHERE substr(name,1,3) = 'lis'\G;

通过以下试验得出结论,假如使用函数作为条件查询,只能返回条件的那一列跟id主键列,一旦返回其他的列就会索引失效!

Mysql使用函数后不走索引怎么优化?

由此优化方案便出来了,假设我们要查name列当中前三个字母是lis的全行数据,然后我们想让他使用到索引,可以使用嵌套查询的方案:

这里进行提示以下:MySQL的IN运算符可以使用索引,但是,有一点需要注意。如果你的IN子句中包含的值很多,那么MySQL可能会选择不使用索引,因为扫描大量的值可能比使用索引更快。这个阈值通常是1000个值,但这个值是可配置的。表内数据太少使用IN也不会使用索引!

EXPLAIN SELECT * FROM demo WHERE id in (SELECT id  from demo WHERE substr(name,1,3) = 'lis') \G;

如下案例显示实际上并未使用到索引

Mysql使用函数后不走索引怎么优化?
上面测试的表当中就两条数据所以显示的in并没有使用索引,如下表内共有一万条数据,然后对主键使用in查询,可以很明显的看到,是使用了索引的。由此可证明in是会使用索引的,只不过mysql会根据权衡利弊到底使用索引快还是不使用索引快。

Mysql使用函数后不走索引怎么优化?

2.通过【虚拟列】让索引生效

Mysql 5.7 中推出了一个非常实用的功能 虚拟列 Generated (Virtual) Columns

  • InnoDB支持在虚拟生成的列上建立二级索引。不支持其他索引类型(主键索引)。在虚拟列上定义的二级索引有时也称为“虚拟索引”。
  • 二级索引可以在一个或多个虚拟列上创建,也可以在虚拟列与常规列或存储生成列的组合上创建。包含虚拟列的二级索引可以定义为UNIQUE
  • 当在虚拟列上使用辅助索引时,由于在INSERT和UPDATE操作期间在辅助索引(辅助又叫二级索引)记录中实现虚拟列值时执行计算,因此需要考虑额外的写成本。即使有额外的写成本,虚拟列上的二级索引也可能比生成的存储列更可取,生成的存储列在集群索引中具体化,从而导致需要更多磁盘空间和内存的更大的表。如果没有在虚拟列上定义二级索引,则会产生额外的读取成本,因为每次检查列的行时都必须计算虚拟列值。

语法:ALTER TABLE 表名称 add column 虚拟列名称 虚拟列类型 GENERATED ALWAYS as (表达式) [VIRTUAL | STORED];

MySQL 在处理 虚拟列存储问题的时候有两种方式:

  • VIRTUAL(默认):不存储列值,在读取表的时候自动计算并返回,不消耗任何存储,这种存储方式仅 InnoDB 支持设置索引。
  • STORED:在插入或更新时计算存储列值,存储的虚拟列需要存储空间,并且 MyISAM 也可以设置索引。

Mysql使用函数后不走索引怎么优化?

下面我们基于substr(name,1,3)函数来创建一个虚拟列:

ALTER TABLE demo add column virtual_name VARCHAR(5) GENERATED ALWAYS as (substr(name,1,3)) VIRTUAL;

对虚拟列添加索引:

ALTER TABLE `demo`.`demo` 
ADD INDEX `virtual_name`(`virtual_name`) USING BTREE;

这时候就可以直接通过虚拟列来完成查询操作了

 EXPLAIN SELECT *  from demo WHERE virtual_name = 'lis';

Mysql使用函数后不走索引怎么优化?

三、总结

假如使用函数作为条件查询,只能返回条件的那一列跟id主键列,一旦返回其他的列就会索引失效!针对于使用函数索引失效问题,可以使用嵌套查询来解决,也可以使用虚拟列来解决!文章来源地址https://www.toymoban.com/news/detail-428190.html

到了这里,关于Mysql使用函数后不走索引怎么优化?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 这样delete居然不走索引

    由于业务变迁,合规要求,我们需要删除大量非本公司的数据,涉及到上百张表,几个T的数据清洗。我们的做法是先从基础数据出发,将要删除的数据id收集到一张表,然后再由上往下删除子表,多线程并发处理。 我们使用的是阿里的polardb,完全兼容mysql协议,5.7版本,RC隔

    2024年02月04日
    浏览(38)
  • 浅析MySQL代价模型:告别盲目使用EXPLAIN,提前预知索引优化策略

    在 MySQL 中,当我们为表创建了一个或多个索引后,通常需要在索引定义完成后,根据具体的数据情况执行 EXPLAIN 命令,才能观察到数据库实际使用哪个索引、是否使用索引。这使得我们在添加新索引之前,无法提前预知数据库是否能使用期望的索引。更为糟糕的是,有时甚至

    2024年02月05日
    浏览(49)
  • MSQL系列(十三) Mysql实战-left/right/inner join 使用详解及索引优化

    Mysql实战-left/right/inner join 使用详解及索引优化 前面我们讲解了B+Tree的索引结构,也详细讲解下Join的底层驱动表 选择原理,今天我们来了解一下为什么会出现内连接外连接,两种连接方式,另外实战一下内连接和几种最常用的join语法 Left join 左表 left join 右表查询 right join 左

    2024年02月05日
    浏览(49)
  • python函数外变量传到函数内处理后不改变函数外的变量,copy模块使用

    先上代码 这段代码先指定了一个a变量是个list,又写了一个abc函数,功能是把外面传进来的list里面的1这个值去掉 按理说在函数内的执行只应该属于函数内的变化,但是实际打印结果是[2,3],函数把外面变量的1删掉了 这不是我想要的,我只想要变量在函数里处理成我想要的,

    2024年02月12日
    浏览(49)
  • mysql织梦索引优化之MySQL Order By索引优化

    在一些情况下,MySQL可以直接使用索引来满足一个ORDER BY 或GROUP BY 子句而无需做额外的排序。尽管ORDER BY 不是和索引的顺序准确匹配,索引还是可以被用到,只要不用的索引部分和所有的额外的ORDER BY 字段在WHERE 子句中都被包括了。 使用索引的MySQL Order By 下列的几个查询都会

    2024年02月04日
    浏览(47)
  • MySQL索引优化与查询优化

    MySQL中提高性能的一个最有效的方式是对数据表设计合理的索引。索引提供了访问高效数据的方法,并且加快查询的速度,因此索引对查询的速度有着至关重要的影响。 使用索引可以快速地定位表中的某条记录,从而提高数据库查询的速度,提高数据库的性能。 如果查询时没

    2024年02月05日
    浏览(48)
  • Elasticsearch 重启后不正常,索引部分为Red

    现象: Elasticsearch 重启后,索引健康状态为Red , kibana 不能访问相关索引。 分析: 重启Elasticsearch 仍然不正常。 索引数量为 1000 多个,查看打开文件数为默认1024 ,怀疑打开文件数不足,导致恢复索引失败。 操作: 修改打开文件数为 65535 , 重启ES 服务, 等待服务加载完成,

    2024年02月12日
    浏览(41)
  • MySQL 参考文档:SQL 语句优化(SELECT 语句优化)之索引条件下推(索引下推)优化

    索引下推优化官方文档说明 (Section 8.2.1.5):https://dev.mysql.com/doc/refman/5.7/en/index-condition-pushdown-optimization.html 1. 什么是索引下推? qquad 索引条件下推 (Index Condition Pushdown,ICP) 是 MySQL 在使用索引从表中检索行时的一种优化方法。在没有 ICP 的情况下,存储引擎遍历索引以定位基

    2024年02月16日
    浏览(42)
  • MySQL 数据存储和优化------MySQL索引原理和优化 ---- (架构---索引---事务---锁---集群---性能---分库分表---实战---运维)持续更新

    Mysql架构体系全系列文章主目录(进不去说明还没写完) https://blog.csdn.net/grd_java/article/details/123033016 本文只是整个系列笔记的第二章:MySQL索引原理和优化,只解释索引相关概念。 索引可以提高查询效率,影响where查询和order by排序,它可以从多方面进行分类,但是实际创建时

    2024年02月02日
    浏览(51)
  • 四、[mysql]索引优化-1

    为employees表添加10w条数据,需要等待一会(嫌时间长的话可以自己手动写一个java脚本)。下边例子都是基于10w数据演示。本章与之前的第二章有很多关联场景,建议先熟悉一下之前的博客。 第二章博客跳转地址 表结构 插入数据语句(执行较慢建议着急的自己写个批插脚本)

    2024年02月06日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包