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

聊聊MySql索引的类型以及失效场景

文章目录

      • 概念
      • 常见的索引
        • 1.B树索引
        • 2.哈希索引
        • 3.全文索引
        • 4.空间索引
        • 5.聚集索引
      • 如何设计合理?
        • 1.明确索引需求
        • 2.选择索引列
        • 3.选择索引类型
        • 4.考虑索引维护开销
        • 5.设计联合索引
        • 6.删除不必要索引
        • 7.关注索引统计信息
        • 8.测试查询效果
      • 常见不生效场景
        • 1.全表扫描
        • 2.索引列计算
        • 3.模糊查询未用前置匹配
        • 4.复合索引条件次序错误
        • 5.or条件索引无效
        • 6.子查询或关联查询inner side未用索引
        • 7.数据分布严重不均匀
        • 8.返回未命中索引覆盖字段
        • 9.索引统计信息没有及时更新
      • 总结
      • 写在最后

579a429daf314744b995f37351b46548

概念

索引是数据库管理系统中一个重要的优化结构,目的是提高数据库查询和操作的速度。

索引的工作原理是对数据库表中的一列或多列的值进行预排序,然后存储该列值与数据行的地址映射,在查询时可以直接查找到数据,而无需全表扫描。


常见的索引

image-20231011135654419

1.B树索引

最常见的索引类型,可以对一个或多个列创建索引。

2.哈希索引

通过哈希函数直接定位到数据行。查找速度极快,但只支持等值查询。

3.全文索引

可以对文本中的关键词创建索引,支持模糊查询。

4.空间索引

用于空间数据类型的索引,可以优化空间计算。

5.聚集索引

索引结构和数据结构相结合,只能有一个聚集索引。


如何设计合理?

image-20231011143716629

1.明确索引需求

​ 分析查询语句和业务场景,确定需要创建索引的列,以优化查询性能。

2.选择索引列

​ 选择区分度高、查询频繁的列作为索引列。避免冗余和相关列的索引。

3.选择索引类型

​ 根据查询方式选择合适的索引类型,如B树索引、哈希索引、全文索引等。

4.考虑索引维护开销

​ 写入操作会增加索引维护开销。权衡查询优化与维护成本。

5.设计联合索引

​ 多个列的联合索引可以覆盖更多查询,但要注意索引列顺序。

6.删除不必要索引

​ 清理冗余和未使用的索引,减少维护损耗。

7.关注索引统计信息

​ 分析索引的使用情况,优化设计。

8.测试查询效果

​ 不同场景测试索引设计的查询性能,验证索引有效性。


常见不生效场景

image-20231011143952193

1.全表扫描

​ SQL语句中没有对索引列进行过滤条件限定,导致全表扫描,索引不生效。

​ 下面是一个全表扫描导致索引失效的例子:

CREATE TABLE users (id INT PRIMARY KEY,name VARCHAR(50),age INT, KEY idx_age (age)
);SELECT * FROM users WHERE name = 'John';

上面创建了users表,并在age列上创建了索引idx_age。但在查询时,条件是name列,而没有使用索引列age进行限定,这会导致全表扫描,idx_age索引不会生效。如果查询改为:

SELECT * FROM users WHERE age = 30 AND name = 'John';

先用索引列age进行过滤,再联合name一起查找,这样可以利用到idx_age索引,避免全表扫描,提高查询效率。

2.索引列计算

​ 对索引列进行算数运算、函数转换、类型转换等,结果索引不再生效。

​ 下面是一个索引列计算导致索引失效的例子:

CREATE TABLE users (id INT PRIMARY KEY,age INT, KEY idx_age (age) 
);SELECT * FROM users WHERE age + 3 = 33;

上面在age列上创建了索引idx_age。但查询条件中对age进行了计算,将age+3进行比较。这导致索引idx_age无法起到作用。因为计算后age的值已经改变,无法直接用于索引查找。改写为不计算age的形式:

SELECT * FROM users WHERE age = 30; 

直接比较age的值,这样可以充分利用idx_age索引,避免表扫描,提高查询效率。

3.模糊查询未用前置匹配

​ like语句的模糊匹配没有用%放在查询条件后面,索引的优势无法利用。

下面是一个模糊查询未用前置匹配导致索引失效的例子:

CREATE TABLE users (id INT PRIMARY KEY,name VARCHAR(50),KEY idx_name (name)
);SELECT * FROM users WHERE name LIKE '%John';

上面在name列上创建了索引idx_name。但模糊查询中,使用了%John方式,没有指明前置匹配。这种情况下,idx_name索引很难发挥作用,执行会变成全表扫描。改为使用前置匹配的形式:

SELECT * FROM users WHERE name LIKE 'John%';

指明 name 以John开头的条件,这样可以利用索引idx_name进行前置匹配优化,避免全表扫描。

4.复合索引条件次序错误

​ 复合索引的条件没有按索引建立的顺序使用,导致部分索引无法生效。

下面是一个复合索引条件次序错误导致部分索引失效的示例:

CREATE TABLE users (id INT PRIMARY KEY, last_name VARCHAR(50),first_name VARCHAR(50),KEY idx_name (last_name, first_name)
);SELECT * FROM users WHERE first_name = 'John' AND last_name = 'Smith';

上面在last_name和first_name上创建了复合索引idx_name。但是查询条件的顺序是first_name在前,last_name在后。这与索引次序相反,导致索引只能生效于first_name条件,但无法生效于last_name条件。如果调整查询为:

SELECT * FROM users WHERE last_name = 'Smith' AND first_name = 'John';

保持与索引次序一致,那么idx_name索引可以完全生效,避免表扫描,提高查询效率。

5.or条件索引无效

​ or条件使得索引无法正确限定范围,无法利用索引进行筛选。

or条件导致索引失效的示例如下:

CREATE TABLE users (id INT PRIMARY KEY,age INT, name VARCHAR(50),KEY idx_age (age),KEY idx_name (name)
);SELECT * FROM users WHERE age = 30 OR name = 'John';

上面在age和name列上分别创建了单列索引。但是查询条件使用了or进行连接,这导致索引无法正确限定范围进行过滤。因为age=30的记录和name='John’的记录可能是两组没有交集的记录。使用or时就需要扫描更大范围,索引效率下降。可以改写为:

SELECT * FROM users WHERE age = 30
UNION 
SELECT * FROM users WHERE name = 'John';

将or拆分为两个查询语句,每个查询只有一个条件,可以独立利用原有的索引,避免全表扫描。所以or条件往往会导致合理利用不到索引,需要特别注意。

6.子查询或关联查询inner side未用索引

​ 子查询或关联查询的内层查询没有用到合的索引。

一个子查询或者关联查询inner side未使用索引导致外层索引失效的示例如下:

SELECT * FROM users 
WHERE id IN (SELECT user_id FROM orders WHERE order_date = '2020-01-01'
);

外层查询在users表上根据id进行了索引查询。但是子查询orders表的查询没有使用索引,会全表扫描orders表来做IN查询。这会导致外层users表的id索引无效。可以这样修改:

SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders WHERE order_date = '2020-01-01'INDEX (order_date)  
);

在子查询orders表查询中,添加order_date列的索引,这样子查询可以利用索引进行筛选。外层的id索引也随之生效,避免全表扫描users表。所以要注意嵌套查询的内层查询也要注意索引的使用,否则容易导致外层索引失效。

7.数据分布严重不均匀

​ 当索引列数据分布严重不均匀时,比如大量重复数据,索引效率会下降。

数据分布不均匀导致索引失效的一个典型例子如下:

CREATE TABLE users (id INT PRIMARY KEY,gender CHAR(1) DEFAULT 'm',KEY idx_gender (gender)
);INSERT INTO users(id) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); 

上面在gender列创建了索引idx_gender。但是数据插入时,gender列都是默认值’m’,分布完全不均匀。此时如果查询:

SELECT * FROM users WHERE gender = 'm';

索引idx_gender实际上无法生效,因为几乎全表数据都匹配条件。会走全表扫描,而无法利用到索引的优点。这种数据分布极不均匀的情况下,对应的索引效果会大打折扣。要避免这种情况,应该在创建索引时注意对应数据的分布情况,对已存在索引的表也要定期分析数据分布,避免索引失效。

8.返回未命中索引覆盖字段

​ 查询需要返回的字段没有完全被复合索引覆盖。

一个复合索引覆盖字段未命中导致索引失效的示例如下:

CREATE TABLE users (id INT PRIMARY KEY,last_name VARCHAR(50),first_name VARCHAR(50),age INT,KEY idx_name_age (last_name, first_name, age)  
);SELECT id, last_name FROM users WHERE last_name='Smith';

这里在last_name,first_name和age上创建了复合索引idx_name_age。查询语句的where条件可以利用这个复合索引。但是SELECT返回的字段id和last_name不完全被idx_name_age索引覆盖。这种情况下,查询还是需要回表去寻找id字段的数据,idx_name_age索引就未能完全生效。解决方法是创建覆盖需要返回的所有字段的索引:

CREATE INDEX idx_name_id ON users (last_name, first_name, id);  

或者将查询需要的所有字段都放入复合索引中。所以复合索引的字段覆盖也需要注意,否则索引的利用效率会大打折扣。

9.索引统计信息没有及时更新

​ 导致查询优化器误判查询成本,选择了非最优索引。

示例如下:

CREATE TABLE users (id INT PRIMARY KEY,age INT, phone VARCHAR(15),KEY idx_age(age),KEY idx_phone(phone)
);INSERT INTO users VALUES 
(1, 35, '13800000000'),
(2, 40, '13800000001'), 
(3, 25, '13800000002');ANALYZE TABLE users; -- 统计信息默认采样扫描表EXPLAIN SELECT * FROM users WHERE age = 40;

开始我们对users表做analyze,收集表的统计信息,包括索引的基数估算等。但analyze默认就是对表做抽样扫描,如果表数据发生大量变更,索引统计信息就会失效。explain显示的结果可能是based on idx_phone, 而不是最优的idx_age索引。这就导致了选择错误索引的问题。解决方法是及时收集更新统计信息:

ANALYZE TABLE users UPDATE INDEXES;  

或者在重要SQL语句前强制绑定使用的索引:

SELECT * FROM users FORCE INDEX(idx_age) WHERE age = 40;

所以及时更新统计信息和合理使用optimizer hints都可以避免这类问题。


总结

​ 了解索引的机制和原理,合理设置索引,可以使查询效率大大提升,从而提升后端的运行效率

写在最后

感谢您的支持和鼓励! 😊🙏

如果大家对相关文章感兴趣,可以关注公众号"架构殿堂",会持续更新AIGC,java基础面试题, netty, spring boot, spring cloud等系列文章,一系列干货随时送达!

相关文章:

聊聊MySql索引的类型以及失效场景

文章目录 概念常见的索引1.B树索引2.哈希索引3.全文索引4.空间索引5.聚集索引 如何设计合理?1.明确索引需求2.选择索引列3.选择索引类型4.考虑索引维护开销5.设计联合索引6.删除不必要索引7.关注索引统计信息8.测试查询效果 常见不生效场景1.全表扫描2.索引列计算3.…...

零代码编程:用ChatGPT批量调整文件名称中的词汇顺序

文件夹里面很多文件,需要批量挑战标题中的一些词组顺序:“Peppa Pig - Kylie Kangaroo (14 episode _ 4 season) [HD].mp4”这个文件名改成“14 episode _ 4 season _ Peppa Pig - Kylie Kangaroo.mp4”,可以在ChatGPT中输入提示词&#xff1…...

stm32 hal库 st7789 1.54寸lcd

文章目录 前言一、软件spi1.cubemx配置2.源码文件 二、硬件spi1.cubemx配置2.源码文件3.小小修改 总结 前言 1.54寸lcd 240*240 一、软件spi 1.cubemx配置 一定要注意把这几个东西上拉。 使用c8 2.源码文件 我使用的是中景园的源码,他本来是是标准库的稍微修改…...

【arm实验1】GPIO实验-LED灯的流水亮灭

linuxlinux:~/study/01-asm$ cat asm-led.S .text .global _start _start: 1.设置GPIOE寄存器的时钟使能 RCC_MP_AHB4ENSETR[4]->1 0x50000a28 LDR R0,0X50000A28 LDR R1,[R0] 从r0为起始地址的4字节数据取出放在R1 ORR R1,R1,#(0x1<<4) 第4位设置为1 ORR R…...

MySQL关联数据表操作方式

1、准备工作&#xff08;创建数据表&#xff09; create table employee( emp_id int primary key, name varchar(20), birth_date date, sex varchar(1), salary int, branch_id int, sup_id int );create table client( client_id int primary key, client_name varchar(20)…...

SMOS数据处理,投影变换,‘EPSG:6933‘转为‘EPSG:4326‘

在处理SMOS数据时&#xff0c;遇到了读取nc数据并存为tif后&#xff0c;影像投影无法改变&#xff0c;因此全球数据无法重叠。源数据的投影为EPSG:6933&#xff0c;希望转为EPSG:4326。 解决代码。 python import os import netCDF4 as nc import numpy as np from osgeo impo…...

游戏服务端性能测试实战总结

导语&#xff1a;近期经历了一系列的性能测试&#xff0c;涵盖了Web服务器和游戏服务器的领域。在这篇文章中&#xff0c;我将会对游戏服务端所做的测试进行详细整理和记录。需要注意的是&#xff0c;本文着重于记录&#xff0c;而并非深入的编程讨论。在这里&#xff0c;我将与…...

塔望食观察 | 中国海参产业发展现状及挑战

海参&#xff0c;一个古老的物种&#xff0c;堪称海底活化石&#xff0c;据资料显示&#xff0c;海参在地球上存活超过6亿年&#xff0c;比恐龙还早。海参的药用、食疗和营养滋补价值极高&#xff0c;清朝学者赵学敏编的《本草纲目拾遗》有这样的叙述&#xff1a;“海参性温补&…...

springboot 捕获特点异常信息并处理

前端获取效果图 springboot 捕获特点异常信息并处理 import com.one.utils.JSONResult; //JSONResult定义处理结果对象 import org.springframework.web.bind.annotation.ExceptionHandler...

【Spring框架学习3】Spring Bean的作用域 及 生命周期

一、Spring Bean的作用域有哪些&#xff1f; Spring框架支持以下五种Bean的作用域&#xff1a; Singleton&#xff1a;这是默认的作用域&#xff0c;在每个Spring IoC容器中只有一个Bean的实例(IoC初始化后)。Spring 中的 bean 默认都是单例的&#xff0c;是对单例设计模式的…...

多线程并发篇---第四篇

系列文章目录 文章目录 系列文章目录一、Java中synchronized 和 ReentrantLock 有什么不同?二、有三个线程T1,T2,T3,如何保证顺序执行?三、SynchronizedMap和ConcurrentHashMap有什么区别?一、Java中synchronized 和 ReentrantLock 有什么不同? 相似点: 这两种同步方式有…...

vs code 添加vue3代码模板方法

最终效果 vs code 添加vue文件模板用于通过简写自动生成代码 操作步骤如下 1.找到vue模板代码编写入口 2.修改模板内容 2.1 vue.json内容 {// Place your snippets for vue here. Each snippet is defined under a snippet name and has a prefix, body and// description. T…...

怎么通过Fiddler对APP进行抓包?以及高级应用场景分析

前言 我们经常需要用到Fiddler做代理服务器对Web、APP应用进行抓包&#xff0c;以便我们对接口功能进行测试调试&#xff0c;定位问题等。这篇将讲述怎么通过Fiddler对APP进行抓包&#xff0c;以及简单介绍一些高级应用场景。 首先&#xff0c;附上Fiddler使用的环境配置清单…...

centos下安装配置redis7

1、找个目录下载安装包 sudo wget https://download.redis.io/release/redis-7.0.0.tar.gz 2、将tar.gz包解压至指定目录下 sudo mkdir /home/redis sudo tar -zxvf redis-7.0.0.tar.gz -C /home/redis 3、安装gcc-c yum install gcc-c 4、切换到redis-7.0.0目录下 5、修改…...

【angular】TodoList小项目(已开源)

参考&#xff1a;https://segmentfault.com/a/1190000013519099 文章目录 准备工作headerTodo、Doing、Done样式&#xff08;HTMLCSS&#xff09;功能&#xff08;TS&#xff09;将输入框内容加入todoList&#xff08;addTodo&#xff09;将todo事件改到doing 服务 参考开源 效…...

【Java 进阶篇】HTML块级元素详解

HTML&#xff08;Hypertext Markup Language&#xff09;是用于创建网页的标记语言。在HTML中&#xff0c;元素被分为块级元素和内联元素两种主要类型。块级元素通常用于构建网页的结构&#xff0c;而内联元素则嵌套在块级元素内&#xff0c;用于添加文本和其他内容。本文将重点…...

CSS设置鼠标样式和添加视频样式

鼠标的样式 <div style"cursor: default">默认鼠标的样式</div><div style"cursor: pointer">小手样式</div><div style"cursor: move">移动样式</div><div style"cursor: text">文本样式&…...

项目文件上传到行云codeup teambition

接手公司好几年的老项目&#xff0c;在行云上已经有1.9G的大小所以被限制上传了 只有花钱扩容或者重新建库。 1.重新建库&#xff1a;登录你的行云账户在代码库中新建代码库&#xff08;网上有详细的&#xff09; 创建成功后的库中只有readme文件。 2.复制代码库的下载地址 …...

现货黄金和实物黄金有什么区别?

在黄金投资市场中&#xff0c;现货黄金和实物黄金都是两种比较受欢迎的黄金投资品种。想想越来越多人认识到黄金投资的重要性&#xff0c;那么要选择一个投资品种&#xff0c;应该选哪个黄金投资品种呢&#xff1f;下面我们就来讨论一下这两者有何区别&#xff0c;以及投资者应…...

/dev下没有video0这个文件(ubuntu无法打开摄像头)

文章目录 硬件问题一、查看虚拟机摄像头连接情况二、解决红色报错三、虚拟机硬件处理内容问题一、设备号二、视频格式问题硬件问题 一、查看虚拟机摄像头连接情况 报错详情 ERROR: cannot launch node of type [image_view/image_view]: image_view ROS path [0]=/opt/ros/m…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...