当前位置: 首页 > news >正文

mybatisPlus的@TableLogic逻辑删除注解导致联合索引失效的坑

文章目录

    • 1.问题
    • 2.原因
    • 3.解决方法
      • 3.1 方法1
      • 3.2 方法2
    • 4. 建索引的几大原则
      • 4.1.最左前缀匹配原则,非常重要的原则
      • 4.2.=和in可以乱序
      • 4.3.尽量选择区分度高的列作为索引
      • 4.4.索引列不能参与计算,保持列“干净”
      • 4.5.尽量的扩展索引,不要新建索引
    • 5.好文分享
    • 6.总结

1.问题

    假设一个mysql的一张单表叫student数据量有500w左右,如果没有选择适当的列加索引的话,相关的查询就会全表扫描,使用的是mybatisPlus作为ORM框架,并且在实体上的逻辑删除字段del(0:否,1:是)上加了@TableLogic注解,那么StudentService中的业务查询代码如下所示:

this.getOne(Wrappers.<Student>lambdaQuery().eq(Student::getName, xxxx).eq(Student::getAddress,xxxx).last("limit 1"))

    如果在student的name,address两列上建立了联合索引如下:

ALTER TABLE student ADD INDEX `index_name_address` (`name`,`address`); -- 索引默认是BTREE

    请问各位看官上面那个StudentServer的this.getOne的查询有没有走index_name_address索引?

    答案是:不会走索引,可以使用explain查根据上面业务代码的sql的执行计划

explain SELECT * FROM student WHERE name = 'xxxx' AND address = 'xxxxxx' LIMIT 1

    如果按照上面的业务代码使用眼睛翻译的sql确实会认为是根据name和address两个条件来查的,但实际上却不是这种的,这里也是有点坑的,如果你以为是这种加索引的,那么即使是加了索引也不会走索引,在那么大数据量的表中加索引还是有风险的,那如何来处理解决呢? 请听下面分析讲解。

2.原因

    首先可以将mybatisPlus的sql打印开开,然后在测试环境写一个test方法,测试下上面那个业务代码,把sql抓到,然后你就会豁然开朗了,开启mybatisPlus的sql打印日志配置如下:

mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpltypeAliasesPackage: xxx.xxxx.entitymapper-locations: classpath:mapper/*.xml

    在测试环境写一个test用例方法就省略了,抓到的sql如下:

SELECT * FROM student WHERE del = 0 AND ( name = 'xxxx' AND address = 'xxxxxx') LIMIT 1

    问题的根本原因就是mybatisPlus使用了@TableLogic注解在实体中标注了逻辑删除字段,最终的sql会将逻辑删除的字符放在一个条件上,会导致联合索引失效(最左匹配的原则),如果生产表数据太大,sql索引失效导致全表扫描,在并发比较高的情况下,一个sql的慢会将mysql数据库cpu干到百分之好几百,导致业务系统不可用,验证可能直接把mysql数据库拖垮,这种就是生产级别的事故了。

3.解决方法

3.1 方法1

ALTER TABLE student ADD INDEX `index_del_name_address` (`del`,name`,`address`);

    修改原索引

3.2 方法2

ALTER TABLE student ADD INDEX `index_name` (`name`);
ALTER TABLE student ADD INDEX `index_address` (`address`);

    这种方式建议一开始就这种搞,生产单表数据量太大,不建议删除之前的索引后新增两个单列索引

4. 建索引的几大原则

4.1.最左前缀匹配原则,非常重要的原则

    mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

4.2.=和in可以乱序

    比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。

4.3.尽量选择区分度高的列作为索引

    区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录。

4.4.索引列不能参与计算,保持列“干净”

    比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’)。

4.5.尽量的扩展索引,不要新建索引

    比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。

    总之,索引不是越多越好越快,而是加的恰到好处,所以遵循上面的原则来加是比较好的。

5.好文分享

https://www.bilibili.com/video/BV1UL411z7WD/?buvid=XX3844F3338BD8CFE89E44F906B4309A8CD6E&from_spmid=main.my-favorite.0.0&is_story_h5=false&mid=3McxpjV8dqbNqf%2FOSLyb1A%3D%3D&p=1&plat_id=116&share_from=ugc&share_medium=android&share_plat=android&share_session_id=3c6b1623-f34f-4fad-8b07-62e11e04b9f8&share_source=WEIXIN&share_tag=s_i&spmid=united.player-video-detail.0.0&timestamp=1723546033&unique_k=XitSYec&up_id=3493270011251381https://www.cnblogs.com/zmc60/p/14533123.html
https://mp.weixin.qq.com/s/hcmRh493yWJUJTJl0tlZWw
https://tech.meituan.com/2014/06/30/mysql-index.html

6.总结

    当生产单表数据量上百万级别的时候,如果要修改表结构的DDL操作,加索引这种操作都还是有一定的风险的,建议在业务低峰期操作,还是要相当的小心,尽量不要去随意操作,否则一个不小心就把系统搞挂了,那个可是要背锅的,mysql在表数据量非常大的时候能力就相对来说弱了一点,所以需要寻求强悍的在大数据量下的查询分析引擎方案,mysql、redis等单一数据库撸到底(可以尝试一些新东西,然后组合搭配使用)已经在这种大数据体量下力不从心了,所以就需要大数据的架构来解决大数据量的写入查询分析等痛点问题,本次分享到此结束,希望我的分享对你有所启发和帮助,请一键三连,么么么哒!

http://www.lryc.cn/news/427447.html

相关文章:

  • C# 隐式转换和显式转换
  • 入门网络安全工程师要学习哪些内容
  • 深入理解 Go 并发原语
  • 计算机毕业设计选题推荐-springboot 基于springboot的宠物健康顾问系统
  • 数据结构—— 初识二叉树
  • 2024.08.09校招 实习 内推 面经
  • IDEA中设置类和方法的注释
  • Adobe Premiere Pro 2023-23.6.7.1 解锁版下载与安装教程 (一款专业的视频编辑软件)
  • openGauss 6.0安装过程解除对root用户依赖之gs_preinstall
  • IOS 10 统一颜色管理和适配深色模式
  • Linux目录结构及基础查看命令和命令模式
  • UDP和TCP协议段格式分析
  • Go语言基础--条件判断(if语句)
  • 白骑士的C#教学实战项目篇 4.2 图形用户界面(GUI)应用
  • 【Java学习】反射和枚举详解
  • leetcode-461. 汉明距离
  • rpmbuild 将二进制文件 strip,文件 md5 发生改变
  • selenium爬取搜狗网站新闻的小Demo
  • R 语言学习教程,从入门到精通,R CSV 文件使用(17)
  • 【LLM之Base Model】Weaver论文阅读笔记
  • 泰坦尼克号 - 从灾难中学习机器学习/Titanic - Machine Learning from Disaster(kaggle竞赛)第一集(了解赛题)
  • 使用C++调用PyTorch模型的弯弯绕绕,推荐LibTorch加载,C++处理
  • 实现异形(拱形)轮播图
  • 【软件测试】2024年职业院校技能大赛高职组“软件测试”赛项样题
  • python数组和队列
  • Vision Transformer(ViT)一种将Transformer架构应用于计算机视觉领域的模型
  • 得到任务式 大模型应用开发学习方案
  • 使用el-menu跳转时偶尔会出现路由已经变了,但是页面却显示空白的情况
  • C语言家教记录(七)
  • 【数据结构】——十大排序详解分析及对比