当前位置:首页 > 文章列表 > 数据库 > MySQL > 不会吧,不会吧?MySQL 索引最佳实践你不看看

不会吧,不会吧?MySQL 索引最佳实践你不看看

来源:SegmentFault 2023-01-16 12:29:41 0浏览 收藏

小伙伴们有没有觉得学习数据库很有意思?有意思就对了!今天就给大家带来《不会吧,不会吧?MySQL 索引最佳实践你不看看》,以下内容将会涉及到MySQL、Java,若是在学习中对其中部分知识点有疑问,或许看了本文就能帮到你!

作者爱说话

忙忙碌碌的一周又过去了,这周最大的乐趣就是买了个小音箱,又可以下班的时候开始愉快的开始练琴了,程序员嘛,还是得培养点艺术细菌。哈哈

这周本来没想好写什么东西,刚好周五公司进行了内部技术分享,内容为《MySQL索引讲解 + 最佳实践》,摘出了几条重要,和较常见的和大家一起分享,当然还有很多没有涉及到,关于索引的知识点,就不具体展开讲解,本来想转载一篇文章与大家分享,但是卑微的我还没加上原作者微信,有兴趣的话可以公众号内回复“唯一索引和普通索引”。我将原文地址推荐给你。

现在你可以洗洗手,打开你的 Naviact 和王经理一起动手实践,知识吸收 + 100%

温馨提示:文末附建表语句。

索引前戏

王经理 ?:天苍苍,野茫茫,索引查询帮大忙。

小林小声 bb:经理好像个憨批。

王经理:林步动,你在说什么?

王经理的砖头

王经理的砖头

小林:没没没,我说经理,好才气!这个诗写的,啧啧啧,真是 ? 牛掰 glass

王经理:算你小子,今天有眼力见。那我考考你,你能概括下索引的优点和缺点嘛?

小林:(淦,又考我) 经理,《高性能 MySQL》一书中总结的 MySQL 的优点是

  • 减少查询需要扫描的数据量(加快了查询速度)
  • 减少服务器的排序操作和创建临时表的操作(加快了groupby和orderby等操作)
  • 将服务器的随机IO变为顺序IO(加快查询速度)

至于缺点嘛,就是索引也是数据,需要存储,因此会带来额外的存储空间占用。其次,在插入,更新和删除操作的同时,需要维护索引,因此会带来额外的时间开销

小美:步动,你今天好帅啊

小林:????

王经理:今天,步动说的很对阿,我再来总结下索引的缺点

  • 索引占用磁盘或者内存空间
  • 减慢了插入更新操作的速度

但是实际上,在一定数据范围内(索引没有超级多的情况下),建立索引带来的开销是远远小于它带来的好处的,但是我们仍然要防止索引的滥用。

王经理:林步动,你骄傲啥,快给我从桌子上下来!我们今天的重点不在这里,重点是讲解一下 MySQL 的索引具体在生产中的最佳实践方法。拿起小本本,打开 Naviact,动起来。

最佳实践

前置知识 :EXPLAIN


1,最左前缀法则

EXPLAIN SELECT * FROM `employee_information` WHERE age = 23 AND position = "dev"

WHERE 条件列的,从索引的最左前列开始,且不跳过索引中的列,一旦未以最从左前列开始,索引就失效。意思就是 是兄弟,就来砍我啊,不对。应该是 带头大哥不能死,中间兄弟不能断

由最左前缀原则引申出的索引冗余问题: 根据最左索引原则,我们不难得出,index(a,b)相当于创建了二个索引index(a)、index(a,b)。也可以类推,index(a,b,c)相当于创建了三个索引index(a)、index(a,b)、index(a,b,c)。

那么,不妨多问自己一个为什么?? 索引冗余会带来什么问题?一张表设置几个索引以内最佳? (可以参考阿里 Java 开发手册,或《高性能的 MySQL》一书)


2,不在索引列上做任何操作(计算、函数、(自动 or 手动)类型转换),会导致索引失效而转向全表扫描

`EXPLAIN SELECT * FROM 
employee_information` WHERE LEFT(name,3) = 'bud'
``

拿该条 SQL 举例说明,我需要一条条取出 name,进行函数操作,然后逐条与限定的条件(bud)进行比较,所以没办法用索引,只能进行全表扫描。

那么,会不会有这么一种情况。在你不经意的时候, MySQL 偷偷的在你的索引列上做了操作?导致我们的索引失效了。

就比如,隐式转换


3,存储引擎不能使用索引中范围条件右边的列(若中间索引列用到了范围(>、

`EXPLAIN SELECT * FROM 
employee_information` WHERE name = 'budongli' AND age > 23 AND position = "dev"
``

可以看到 type = range,实际上 age 用到了索引(可以观察 key_len),只是说这个索引表达的是范围,导致 position 用不上索引


4,尽量使用覆盖索引(只访问索引的查询(索引列包含查询列)),减少 SELECT * 语句

EXPLAIN SELECT name FROM `employee_information` WHERE name = 'budongli'

我们在相应的 SELECT 操作中使用了覆盖索引,通俗一点讲就是查询的列被索引覆盖,使用到覆盖索引查询速度会非常快,SQl优化中理想的状态。

需要注意的是,当 Using where 和 Using index 同时出现的时候,此时 Using where 只是用来从索引中查找数据,此数据如果不是用来过滤,那么就是用来读取,以避免回表读取数据行。

如果我们只爱使用 SELECT * ,那么完蛋。

Extra 会告诉你,查询的列未被索引覆盖,进而通过 where 条件过滤获取所需数据,


5,MySQL 在使用不等于(!= 或者 )的时候无法使用索引导致全表扫描,is null 或者 is null not 也不会走索引

EXPLAIN SELECT * FROM `employee_information` WHERE name != 'budongli'

这条和 Shit 一样的 SQL ?,在我是实习生的时候也写过。

尽可能把类似这种判断落在业务层,数据库很累,不给他加压力。保护数据库,从你我做起。


6,like 以通配符开头(‘$abc’) MySQL 索引失效会变成全表扫描操作

就像查字典一样,比如要查拼音首字母是ch的字,按顺序翻完以ch开头的页就能有结果,在这个 SQL 语句中我们想去查 名字开头是“budon”,利用索引顺序查就ok了,很快就能查出来了。

EXPLAIN SELECT * FROM `employee_information` WHERE name like 'budon%'

但要是假设你想在字典里查拼音包含an的字,那就只能一页一页翻完整个字典才能知道哪些是需要的,此时就相当于无法走索引,只能走全表扫描。

EXPLAIN SELECT * FROM `employee_information` WHERE name like '%budon%'


7,少用 or 或者 in

`EXPLAIN SELECT * FROM 
employee_information` WHERE name = "budongli" or name = "xiaomei"
``

MySQL 的查询优化器是一个非常复杂的部件,它使用了非常多的优化策略来生成一个最优的执行计划: 在使用 or 或者 in 的时候, MySQL 不一定会使用索引,MySQL 内部优化器会根据每张表或者索引的页面个数、索引的基数、索引和数据行的长度、索引的分布等七七八八,九九十十等多个因素去整体评估是否使用索引。有非常多的原因会导致 MySQL 选择错误的执行计划,比如统计信息不准确、不会考虑不受其控制的操作成本(用户自定义函数、存储过程)。

归根结底,MySQL 认为的最优跟我们想的不一样(我们希望执行时间尽可能短,但 MySQL 值选择它认为成本小的,但成本小并不意味着执行时间短)等等。

所以说,MySQL 内部优化器有时候也是个笨蛋,很有可能选错。当然如果你觉得走一个固定的索引,这个 SQL 语句会快的飞起,请别客气使用 FORCE INDEX 与优化器进行 Battle

问题时间到了

如果一张表的某个字段即可以建唯一索引,又可以建普通索引,假设你是公司的 DBA,从性能角度考虑来讲,你会如何选择?选择的依据是什么?

(建议小伙伴可以主动去思考思考,动手实践实践,当然公众号内也给你准备了较为详细的分享,你可以在公众号内回复 “唯一索引和普通索引” ,我将与你分享)

建表语句

-- ----------------------------  
-- Table structure for employee_information  
-- ----------------------------  
DROP TABLE IF EXISTS `employee_information`;  
CREATE TABLE `employee_information`  (  
  `id` int(11) NOT NULL,  
  `name` varchar(24) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,  
  `age` int(11) NOT NULL,  
  `position` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,  
  `hire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  
  PRIMARY KEY (`id`) USING BTREE,  
  INDEX `hybrid_index`(`name`, `age`, `position`) USING BTREE,  
  INDEX `age`(`age`) USING BTREE  
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;  
  
-- ----------------------------  
-- Records of employee_information  
-- ----------------------------  
INSERT INTO `employee_information` VALUES (1, 'budongli', 23, 'dev', '2020-06-12 22:21:24');  
INSERT INTO `employee_information` VALUES (2, 'xiaomei', 22, 'dev', '2020-05-06 22:22:10');  
INSERT INTO `employee_information` VALUES (3, 'jingliwang', 30, 'manager', '2018-06-01 22:22:37');  
  
SET FOREIGN_KEY_CHECKS = 1;  

今天关于《不会吧,不会吧?MySQL 索引最佳实践你不看看》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于mysql的内容请关注golang学习网公众号!

版本声明
本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
大厂的高级java开发有什么要求?大厂的高级java开发有什么要求?
上一篇
大厂的高级java开发有什么要求?
苦苦面试了半年,上个月凭借着这份面试题,我一举拿下了阿里,字节跳动和京东的offer!
下一篇
苦苦面试了半年,上个月凭借着这份面试题,我一举拿下了阿里,字节跳动和京东的offer!
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • 笔灵AI生成答辩PPT:高效制作学术与职场PPT的利器
    笔灵AI生成答辩PPT
    探索笔灵AI生成答辩PPT的强大功能,快速制作高质量答辩PPT。精准内容提取、多样模板匹配、数据可视化、配套自述稿生成,让您的学术和职场展示更加专业与高效。
    13次使用
  • 知网AIGC检测服务系统:精准识别学术文本中的AI生成内容
    知网AIGC检测服务系统
    知网AIGC检测服务系统,专注于检测学术文本中的疑似AI生成内容。依托知网海量高质量文献资源,结合先进的“知识增强AIGC检测技术”,系统能够从语言模式和语义逻辑两方面精准识别AI生成内容,适用于学术研究、教育和企业领域,确保文本的真实性和原创性。
    22次使用
  • AIGC检测服务:AIbiye助力确保论文原创性
    AIGC检测-Aibiye
    AIbiye官网推出的AIGC检测服务,专注于检测ChatGPT、Gemini、Claude等AIGC工具生成的文本,帮助用户确保论文的原创性和学术规范。支持txt和doc(x)格式,检测范围为论文正文,提供高准确性和便捷的用户体验。
    30次使用
  • 易笔AI论文平台:快速生成高质量学术论文的利器
    易笔AI论文
    易笔AI论文平台提供自动写作、格式校对、查重检测等功能,支持多种学术领域的论文生成。价格优惠,界面友好,操作简便,适用于学术研究者、学生及论文辅导机构。
    38次使用
  • 笔启AI论文写作平台:多类型论文生成与多语言支持
    笔启AI论文写作平台
    笔启AI论文写作平台提供多类型论文生成服务,支持多语言写作,满足学术研究者、学生和职场人士的需求。平台采用AI 4.0版本,确保论文质量和原创性,并提供查重保障和隐私保护。
    35次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码