探秘MySQL——全面了解索引、索引优化规则
文章目录
- 0.什么是索引
- 1.常用索引分类
- 逻辑维度
- 底层数据结构维度
- 物理维度(InnoDB)
- 2.为什么底层是B+树
- 平衡二叉查找树
- 红黑树
- B树(多叉)
- B+树(多叉)
- 3.MySQL索引优化
- SQL性能分析之explain
- Q.MySQL如何查看查询是否用到了索引
- 优化一:为表添加自增主键
- 优化二:添加唯一索引
- 优化三:添加联合索引
- Q.索引失效场景:联合索引非连续
- 优化四:针对order by的优化
- Q.索引失效场景:order by同时使用ASC 和 DESC
- Q.性别字段适合添加索引吗
- 参考
本博客实战部分仓库:点击跳转github
0.什么是索引
索引是帮助MySQL高效获取数据的数据结构。简单来讲,数据库索引就像是书前面的目录,能加快数据库的查询速度。
对于海量数据来说,它的目录也是很大的,不可能全部存储在内存中,因此索引往往是存储在磁盘上的文件中
1.常用索引分类
逻辑维度
- 唯一索引、主键索引:值唯一,前者可以为null,后者不能为null
- 联合(组合)索引:为多个字段创建的索引,遵循左前缀原则,即从最左边的字段开始匹配
- 普通索引:没什么限制,可重复可为空,都行
底层数据结构维度
hash索引:适用于= <> != IN几种情况,精确查找。仅Memory搜索引擎支持。
B+树索引:适用于范围查找。InnoDB和MyISAM支持。
物理维度(InnoDB)
InnoDB提供的一种分类方式,InnoDB的每张表都会有一个聚集索引,有且仅有一个,这也是该表的物理存储方式;非聚集索引可以有多个。
- 聚簇索引(主键索引):
根据主键构建的索引叫做聚簇索引。将数据存储与索引放到了一块,找到索引也就找到了数据。
优点:检索速度很快,排序查找、范围查找都很不赖;没有回表查询现象。
缺点:主键最好是自增的,因为连续的主键索引性能更好;主键最好设置为不可变,改变主键会导致聚集索引的维护代价很高。- 非聚簇索引(辅助索引):
不是根据主键构建的索引叫做非聚集索引或者二级索引或者辅助索引。
将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置。
缺点:存在回表查询现象
2.为什么底层是B+树
在探讨这个问题前我们先明确一件事: 对于索引的树结构,每个节点称为页,页就是我们上面说的磁盘块,是MySQL数据读取的基本单位。因此,一个节点的读取对应于一次IO操作,底层数据结构的设计应该往减少IO次数的方向进行优化。
如果不知道这几种数据结构的,建议先面向百度学习一下,这不是本文的重点。
平衡二叉查找树
- 缺点:
路数太少,树太深,检索性能有限,而且会导致查找过程中IO次数很多。
红黑树
- 缺点:
1 同样的,路数太少,树太深,检索性能有限;
2 另外,红黑树不是绝对平衡,IO次数会不稳定。
其实所有的二叉树都有类似的局限性。
B树(多叉)
- 优点:
1 路数比较多,成功地将二叉树的瘦长结构优化成了矮胖结构,极大地减少了IO查询次数。
2 另外,叶节点都在同一层上,IO次数是比较稳定的。
其实B树已经比较理想了,那为啥MySQL索引没用B树呢?
- 不足:
1 每个非叶节点存储的是索引+数据,其中数据是一条记录,
试想一下,如果一条记录属性非常多,那么B树的每个节点能存储的数据就会变少,
面对海量的数据,最后B树就会从矮胖型变成瘦长型,IO次数势必无法得到优化
2 注意看叶节点层,不同节点不是连续的,当我们需要进行快速范围检索的时候,B树恐怕无法满足我们的要求。
B+树(多叉)
- 优点:
1 非叶节点仅存储索引,不存储数据,每个节点可存储较多索引值,因此可保证树是矮胖型的,IO次数得到优化
2 叶节点全部在同一层,IO次数十分稳定
3 叶节点保存索引+数据,并且增加了双循环链表的支持,可支持快速范围检索
为什么底层是B+树,现在知道原因了吧,这种设计是不是很巧妙?
3.MySQL索引优化
光了解理论也没什么意思,直接实战。这部分请 下载我在文章一开始提供的github仓库源码,里面有必要的数据。
由于频繁插入数据会导致索引维护代价很大,因此,我没在创建表时添加索引,而是在插入大量数据结束后再手动添加索引。
SQL性能分析之explain
explain可以分析一条sql的优劣,通过mysql反馈我们,需要我们自己去读懂explain的sql执行结果来判断是否要进行优化。
- 使用:
explain sql语句;
建议先看看这个老哥的博客,了解下explain方便我们调优。
Q.MySQL如何查看查询是否用到了索引
执行explain语句,查看结果中的type字段(使用到的索引类型)、possible_keys字段(可用索引,未必是最终使用的)、key字段(实际使用的索引)。
优化一:为表添加自增主键
我的三张表都是使用的InnoDB存储引擎,上面提到了,InnoDB会默认为每张表建立一个聚集索引(主键索引) ,这个聚集索引会以主键为键。因此主键建议自增,且最好不要修改,否则索引维护代价很大。
优化必要性:设置自增主键更加符合主键索引的底层特性(有序、范围查找),使其发挥最高检索效率。并且自增主键后期不建议进行修改。
考虑到我的三张表都没有设置主键自增,因此这是我针对数据库需要优化的第一个地方。
- 表结构修改思路:原id重命名,重新添加自增主键
仅展示一张表
-- ----------------------------
-- 优化1:设置主键自增
-- ----------------------------
DROP TABLE IF EXISTS `claim`;
CREATE TABLE `claim` (`id` int(0) NOT NULL AUTO_INCREMENT,`app_no` char(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,`tree` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
重构表结构之后,再执行data.sql插入数据。
优化二:添加唯一索引
注意:插入大量数据之后再设置索引,可以避免索引的频繁维护。
请看claim这张表,这个app_no字段是唯一的,考虑到我需要经常查询这个字段,我给它设置一个唯一索引。
ALTER TABLE claim
ADD UNIQUE INDEX(app_no);
text表中的index字段也是同理:
ALTER TABLE text
ADD UNIQUE INDEX(`index`);
优化三:添加联合索引
联合索引数据存储方式:先对索引中第一列的数据进行排序,而后在满足第一列数据排序的前提下,再对第二列数据进行排序,以此类推。
优化规则:
1 考虑选择性:选择性=count(distinct 字段名)/count(*)
将选择性最高的列放到索引最前列(但是不是绝对的)。
2 把经常同时出现在where and子句中的字段设置成联合索引
ALTER TABLE text ADD INDEX id_app_no(`id`,application_no,date);SELECT * FROM text
WHERE `id`>1 AND application_no>'EP2567834' AND date>'20170614';
Q.索引失效场景:联合索引非连续
建立联合索引(a,b,c),where c = 5是否会用到索引?为什么?
用不到,因为联合索引遵循左匹配原则,where c=5子句中联合索引直接从a断开了,所以用不到该联合索引。
优化四:针对order by的优化
- 可优化的情况:
# 查询语句
explain select * from text
where application_no>'EP2567834' and date>'20170614'
order by id;
针对这种情况,建立联合索引(application_no,date,id
)能命中索引:
注意:where子句中出现的字段放前面,order by中的字段放后面,效率会更高。
alter table text add index app_no_id(application_no,date,`id`);
Q.索引失效场景:order by同时使用ASC 和 DESC
以下情况索引会无法命中:
SELECT FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
Q.性别字段适合添加索引吗
不适合
性别字段因为可重复肯定只能建立非聚集索引,然而因为非聚集索引叶子节点存储的是索引值和聚集索引值,需要回表。所以在性别这种辨别度较低的字段上建立索引,索引树可能只有两个节点,跟线性查找没有太大区别,并且因为回表的存在导致在聚集索引树和非聚集索引树来回切换反而导致查询时间更慢。并且维护该索引还要一定的开销。
参考
博客1
博客2
博客3
相关文章:

探秘MySQL——全面了解索引、索引优化规则
文章目录0.什么是索引1.常用索引分类逻辑维度底层数据结构维度物理维度(InnoDB)2.为什么底层是B树平衡二叉查找树红黑树B树(多叉)B树(多叉)3.MySQL索引优化SQL性能分析之explainQ.MySQL如何查看查询是否用到…...

战斗力最强排行榜:10-30人团队任务管理工具
工欲善其事,必先利其器。在高效的任务执行过程中,选择灵活轻便的项目管理工具来提升工作效率、适应快速多变的发展诉求,对团队来说,至关重要。但是如果团队不大,企业对这块的预算又有限,大型的团队任务管理…...

2023-03-09干活小计
强化学习: 强化学习用智能体(agent)这个概念来表示做决策的机器。 感知、决策和奖励 感知。智能体在…...

基数排序算法
目录:什么是基数排序?基本原理核心思想实现逻辑代码实现复杂度分析总结什么是基数排序? 基数排序:基数排序(Radix sort)是一种非比较型整数排序算法, 基本思想主要是通过关键字间的比较和移动记…...

项目实战典型案例24——xxljob控制台不打印日志排查
xxljob控制台不打印日志排查一:背景介绍问题截图问题解读二:思路&方案三:过程四:总结一:背景介绍 本篇博客是对xxljob控制台不打印日志排查进行的总结和进行的改进。 目的是将经历转变为自己的经验。通过博客的方…...

旋转框目标检测mmrotate v1.0.0rc1 之RTMDet训练DOTA的官方问题解析整理(四)
关于rotated_rtmdet_l-coco_pretrain-3x-dota_ms.py配置文件的batchsize和学习率设置问题:回答:如何在mmrotate中绘制特征图问题:回答:你好AllieLan,您可以尝试使用https://github.com/open-mmlab/mmyolo/blob/main/de…...

4个顶级的华为/小米/OPPO/Vivo手机屏幕解锁工具软件
有好几次用户发现自己被锁定在他们的华为/小米/OPPO/Vivo设备之外,我们知道这可能是一种非常可怕的体验。在这种情况下,找到安卓手机解锁软件,重新获得手机中重要数据和文件的访问权限。看看这篇文章,因为我们将与您分享什么是解锁…...
华为OD机试题 - 和最大子矩阵(JavaScript)| 机考必刷
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:和最大子矩阵题目输入输出示例一输入输出说明Code思路版权说明华…...
企业电子招标采购系统源码之项目说明和开发类型
项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及…...

Python高频面试题——装饰器(带大家理解装饰器的本质)
装饰器概念装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限验证等场景…...

全方位解读智能中控屏发展趋势!亚马逊Alexa语音+Matter能力成必备
随着智能家居行业逐步从碎片化的智能单品阶段,迈向体验更完整的全屋互联阶段,智能中控屏作为智能家居最佳的入口之一,在年轻人青睐全屋智能装修的风潮下,市场潜力彻底被引爆。 一、为什么是智能中控屏? 在智能音箱增…...
JAVA练习74-括号生成
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 提示:这里可以添加本文要记录的大概内容: 3月10日练习内容 提示:以下是本篇文章正文内容,下面案例可供参考 一、题目-…...
Java ORM开发 更全面的应用场景
1. 一个web系统, 想支持多种数据库, 如同时要用mysql, oracle 需要动态切换数据源? 2. 读写分离, 但读库与写库是不同的类型, 如分别是: mysql, oracle 3. 智能化自动过滤null和空字符串,不再需要写判断非空的代码。 4.动态/任意组合查询条件,不需要提前准备da…...

SpringBoot【基础篇】---- 基础配置
SpringBoot【基础篇】---- 基础配置1. 属性配置2. 配置文件分类3. yaml 文件4. yaml 数据读取1. 读取单一数据2. 读取全部数据3. 读取对象数据yaml 文件中的数据引用1. 属性配置 SpringBoot 通过配置文件 application.properties 就可以修改默认的配置,那咱们就先找…...

手机磁吸背夹散热器制冷快速方案
手机散热器是什么?手机散热器分为几种类型?手机散热的方式都有哪些? 因为经常玩游戏,手机发热得厉害,都可以煎鸡蛋了,心想着要买个东西给手机散散热,没想到还真的有手机散热器。 不知道手机散…...

青岛OJ(QingdaoU/OnlineJudge)部署如何直连数据库批量修改
1.postgres数据库QingdaoU/OnlineJudge用的数据库是postgreSQL,一个关系型数据库。默认端口是5432,我们下载一个navcat 15以上的版本,用来连数据库。2.修改docker-compose.yml文件修改docker-compose.yml,手动添加一个端口&#x…...

渗透测试——信息收集(详细)
信息收集:前言:信息收集是渗透测试除了授权之外的第一步,也是关键的一步,尽量多的收集目标的信息会给后续的渗透事半功倍。收集信息的思路有很多,例如:页面信息收集、域名信息收集、敏感信息收集、子域名收…...

什么是谐波
什么是谐波 目录 1. 问题的提出 2. “谐”字在中英文中的原意 2.1 “谐”字在汉语中的原义 2.2 “谐”字对应的英语词的原义 3.“harmonics(谐波)”概念是谁引入物理学中的? 4.“harmonics(谐波)”的数学解释 1. 问题的提出 “谐波”这个术语用于各种学科&am…...
技术报告:程序员如何开发一个商城型购物网站
前言随着互联网的快速发展,电商行业正成为越来越多人的选择。而作为电商行业的主要参与者之一,商城型购物网站的开发则成为程序员不可避免的任务之一。本文将对商城型购物网站的开发进行详细阐述,包括需求分析、架构设计、技术选型、前后端开…...

DPDK系列之八虚拟化virtio
一、virtio的介绍 在一篇文章中对virtio进行了简单的说明。在早期的虚拟化的过程中,无论是KVM还是Vmware亦或是Xen,每个平台想当然的是自己搞自己的IO接口。这就和现在国内的互联各个平台都是大而全一样,怎么可能我用你的支付接口呢…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...

基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器
一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下,音视频内容犹如璀璨繁星,点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频,到在线课堂中知识渊博的专家授课,再到影视平台上扣人心弦的高清大片,音…...