关于索引应用的一些问题

news2024/12/23 14:26:11

索引是啥:加快检索速度的数据结构

索引的优点和缺点

索引的优点:

1.建立索引后,数据库检索数据速度直线上升(使用正确的话),数据量越大越明显

2.分组和排序的时候,可以利用索引加快速度

3.通过建立唯一索引可以确保数据唯一,不需要加其他限制条件(既建立了索引 又保证了唯一性)

4.连表查询时,基于主外键字段上建立索引,可以带来十分明显的性能提升。

缺点:

1.建立索引会生成本地磁盘文件,需要额外的空间存储索引数据,磁盘占用率会变高。

2.写入数据时,需要额外维护索引结构,增、删、改数据时,都需要额外操作索引。

3.写入数据时维护索引需要额外的时间开销,执行写SQL时效率会降低,性能会下降。

各种索引的优劣

主键索引

首先过长的字段不应该作为主键索引,且主键索引字段应该唯一

所以我们一般用自增ID作为主键索引,能满足这两种需求

但是我们为啥不用UUID作为主键索引呢?这也满足我们的要求啊

因为InnoDB储存引擎在储存索引的时候,使用的是B+树作为数据结构 而B+树是基于二分功能的 也就是它的节点是有序的 (详情可以看下这篇博客B+树)  但UUID是随机的 也就是说我们在建立索引的时候要进行随机插入 而随机插入可能会打乱B+树的现有的形状 而主键索引的叶节点里面包含所有数据 一移动节点会移动数据 这样进行数据迁移的代价极大

但使用自增ID就不会有这个问题,所有新插入的数据都会放到最后。

所以主键又加了一个要求 有序

联合索引

联合索引可以实现索引覆盖 减少二级索引的回表操作从而提高检索速度 或者在分组及排序的时候加快速度

但是举个例子 我们对 a b c字段建立联合索引

那么有三条语句

SELECT * FROM table WHERE a = 1 and b = 1 and c = 1;

SELECT * FROM table WHERE a = 1 and c = 1;

SELECT * FROM table WHERE b = 1 and c = 1; 

只有第三条语句不能使用联合索引

因为查询条件的最左边的条件要和索引的最左边匹配也就是说这里的查询条件的第一个条件一定要是a 才能使用联合索引

且联合索引当遇到范围查询 (>、<) 就会停止匹配 比如

select * from t_user  where age > 20 and reward = 100000;

age可以利用到联合索引 而reward不行

前缀索引

前缀索引就是利用这个字段的前几个字符创建索引 相较于普通的索引 可以节省储存空间 当数据数量高到一定程度时 节省的储存空间将十分可观

但是它的索引节点中,未存储一个字段的完整值,所以MySQL也无法通过前缀索引来完成ORDER BY、GROUP BY等分组排序工作,同时也无法完成覆盖扫描等操作。

全文索引

InnoDB在MySQL 5.6及以后的版本引入的全文索引

全文索引是将存储在数据库中的大段文本中的任意内容信息查找出来的技术

假如说 我们百度搜索 MYSQL很酷 然后看搜索结果 标红的部分就是 和关键词对应的地方

我们的全文索引也就是这样的效果 把要搜索的字段 断成几个词根 然后再全文里面检索

 有没有感觉和模糊匹配的作用差不多(好像是个大模糊匹配)模糊匹配虽然能够实现效果,但随着表越来越大,数据越来越多时,其性能会出现明显下降,而全文索引的推出则能够完美解决该问题,可以利用全文索引代替like%语法实现模糊查询,它的性能会比like%快上N倍。

全文索引的缺陷:

①由于全文索引是基于分词实现的,所以对一个字段建立全文索引后,MySQL会对该字段做分词处理,这些分词结果也会被存储在全文索引中,因此全文索引的文件会额外的大!

②由于全文索引对每个字段值都会做分词,因此当修改字段值后,分词是需要时间的,所以修改字段数据后不会立马自动更新全文索引,此时需要咱们写存储过程,并调用它手动更新全文索引中的数据。

③除开上述两点外,全文索引最大的硬伤在于对中文支持不够友好,类似于英文可以直接通过符号、空格来分词,但中文呢?一个词语来形容就是博大精深,无法精准的对一段文字做分词,因此全文索引在检索中文时,存在些许精准度问题。

唯一索引

唯一索引可以保证数据唯一性 当它搜索的时候只会返回一条数据不会往下查看,而普通索引会向下查看知道不满足条件,所以检索速度会快一些(实际上快不了多少 因为读取行为一次读一个数据页到内存中 而内存中的查询操作很快 详情可见-普通索引VS唯一索引)

插入的时候呢

当当前数据页已经被加载到内存中时

唯一索引:先找到插入位置 看看冲不冲突 不冲突再插入

普通索引: 直接插

差了个cpu操作 也大差不差

但是如果当前数据

就不行了 就是唯一索引是用不了change buffer的 所以每次插入操作都要进行一次I/O操作 而我们知道I/O操作贼**费劲

哈希索引

(我是没见过 但是了解总比不了解强对吧)

哈希索引,也就是数据结构为Hash类型的索引,不过估计大家接触的比较少,毕竟创建索引时都默认用的B+树结构。但要比起查询速度,哈希索引绝对是MySQL中当之无愧的魁首!因为采用哈希结构的索引,会以哈希表的形式存储索引字段值,当基于该字段查询数据时,只需要经过一次哈希计算就可获取到数据。

但哈希结构的致命问题在于无序,也就是无法基于哈希索引的字段做排序、分组等工作。

因此如果你确定一个表中,不会做排序这类的工作,那可以适当选用哈希结构作为索引的数据结构,它会给你带来意想不到的性能收益

索引失效

就是建立好的索引没用上 直接全表扫描了

左或者左右模糊匹配

索引 B+ 树是按照「索引值」有序排列存储的,只能根据前缀进行比较。那左模糊匹配和左右模糊匹配都是前缀未知的

使用函数

假如说我们对value列建立了索引 然后查询的时候用了 WHERE ​LENGTH(name)=6  ​这时候就不会使用索引 原因很简单 我们是对value建立了索引 又不是对函数建立了索引

不过呢 现在MYSQL还真只是函数索引了 我们如果建立 LENGTH(name)索引的话 那再查询的时候就可以走索引了呗

使用表达式

这里失效的理由和使用函数的失效是一样的 例如 WHERE id + 1 = 10

但是呢 如果用 WHERE id = 10 - 1 就可以 因为MYSQL懒的判断 所以我们自己改一改还是可以用的

隐式类型转换

比如我们刚开始 定义了value VARCHAR(20) 但是在查询的时候忘记写单引号了

 比如 WHERE value = 60 MYSQL就会认为你查的是int类型的 然后就索引失效了

而反过来 定义value INT 查询的时候加了单引号 value = '60' 就不会索引失效

为啥呢,因为:MySQL 在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较。而这个转换行为会调用函数

也就是第一种方式就等效于  

where CAST(value AS signed int) = 60;

也就是发生了使用函数造成的索引失效

而第二种方式

where value  = CAST(60 AS signed int);

这次我们的被判断字段没使用函数

联合索引非最左匹配

在上面联合查询的部分介绍了

使用了OR

如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。

不同字段值对比

如果我们用 WHERE name = 'zhangsan'   不会索引失效 但是

如果用        WHERE  name_student = name_teacher 就会失效 不能用两个字段(参数)进行比较(即使建立了 name)

反向范围操作导致索引失效

一般来说,如果SQL属于正向范围查询,例如>、<、between、like、in...等操作时,索引是可以正常生效的,但如果SQL执行的是反向范围操作,例如NOT IN、NOT LIKE、IS NOT NULL、!=、<>...等操作时,就会出现问题,

不过IS NULL虽然是正向查询 但是也会索引失效 IS NOT NULL也会失效

MYSQL优化器造成的索引失效

有时候二级索引的大量I/O操作(回表造成的) 还不如直接全表查询来的快 MYSQL就会自动执行成本更低的操作

例如:SELECT * FROM table WHERE a>1000000 and b <500000;

这个数据有很多行(按几万行估计) 我们的流程为

(在联合索引遇到> <的时候会停止 也就是a使用索引 b不使用)

判断a是否符合要求 然后拿着a的id 回表操作拿到b的数据 判断

而不用索引呢
顺序遍历每一条数据 由于每次加载一个数据页进来 比每条进行回表 减少了很多I/O操作 成本大量减少了

一些索引优化行为

索引覆盖

当要查询的数据全包含在联合索引时 就会直接在索引中取值而避免多次回表操作

例如 SELECT name,age FROM table WHERE.....如果name和age包含在联合索引中 就不会按照正常的二级索引逻辑(找到对应主键 再用主键找到整条记录的数据)

索引下推

也就是将Server层筛选数据的工作,下推到引擎层处理

例如:

SELECT * FROM table where a  > 500 and b = 20;

这条SQL会部分使用索引 只适用a的索引

如果没有索引下推 那么它的执行过程为 首先找到a>500的所有条目 然后回表扫描 判断b是否等于20 然后把符合的结果返回给用户

有了索引下推 就是 找到a>500的条目 同时在联合索引中判断是否符合b=20 不符合的直接筛掉

然后直接去回表拿数据 就减少了几次回表操作


MRR(Multi-Range Read)机制

Multi-Range Read简称为MRR机制,这也是和索引下推一同在MySQL5.6版本中引入的性能优化措施,那什么叫做MRR优化呢?

一般来说,在实际业务中我们应当尽量通过索引覆盖的特性,减少回表操作以降低IO次数,但在很多时候往往又不得不做回表才能查询到数据,但回表显然会导致产生大量磁盘IO,同时更严重的一点是:还会产生大量的离散IO,下面举个例子来理解。

SELECT * FROM `zz_student_score` WHERE `score` BETWEEN 0 AND 59;

上述这条SQL所做的工作很简单,就是在学生成绩表中查询所有成绩未及格的学生信息,假设成绩字段上存在一个普通索引,那思考一下,这条SQL的执行流程是什么样的呢?

  • ①先在成绩字段的索引上找到0分的节点,然后拿着ID去回表得到成绩零分的学生信息。
  • ②再次回到成绩索引,继续找到所有1分的节点,继续回表得到1分的学生信息。
  • ③再次回到成绩索引,继续找到所有2分的节点......
  • ④周而复始,不断重复这个过程,直到将0~59分的所有学生信息全部拿到为止。

那此时假设此时成绩0~5分的表数据,位于磁盘空间的page_01页上,而成绩为5~10分的数据,位于磁盘空间的page_02页上,成绩为10~15分的数据,又位于磁盘空间的page_01页上。此时回表查询时就会导致在page_01、page_02两页空间上来回切换,但0~5、10~15分的数据完全可以合并,然后读一次page_01就可以了,既能减少IO次数,同时还避免了离散IO

MRR机制就主要是解决这个问题的,针对于辅助索引的回表查询,减少离散IO,并且将随机IO转换为顺序IO,从而提高查询效率。

MRR机制中,对于辅助索引中查询出的ID,会将其放到缓冲区的read_rnd_buffer中,然后等全部的索引检索工作完成后,或者缓冲区中的数据达到read_rnd_buffer_size大小时,此时MySQL会对缓冲区中的数据排序,从而得到一个有序的ID集合:rest_sort,最终再根据顺序IO去聚簇/主键索引中回表查询数据。

Index Skip Scan索引跳跃式扫描

限制太多 了解即可 

我们建立了关于 a b c的索引

SELECT * FROM WHERE b = 1 and c = 1;

本来这条SQL是不应该使用索引的 但是MYSQL帮助我们"跳过"了a 强制使用索引

其实也就是MySQL优化器会自动对联合索引中的第一个字段的值去重,然后基于去重后的值全部拼接起来查一遍

使用索引的建议

这里引用https://juejin.cn/post/7149074488649318431的原文

  • ①经常频繁用作查询条件的字段应酌情考虑为其创建索引。
  • ②表的主外键或连表字段,必须建立索引,因为能很大程度提升连表查询的性能。
  • ③建立索引的字段,一般值的区分性要足够高,这样才能提高索引的检索效率。
  • ④建立索引的字段,值不应该过长,如果较长的字段要建立索引,可以选择前缀索引。
  • ⑤建立联合索引,应当遵循最左前缀原则,将多个字段之间按优先级顺序组合。
  • ⑥经常根据范围取值、排序、分组的字段应建立索引,因为索引有序,能加快排序时间。
  • ⑦对于唯一索引,如果确认不会利用该字段排序,那可以将结构改为Hash结构。
  • ⑧尽量使用联合索引代替单值索引,联合索引比多个单值索引查询效率要高。

同时,除开上述一些建立索引的原则外,在建立索引时还需有些注意点:

❶值经常会增删改的字段,不合适建立索引,因为每次改变后需维护索引结构。

❷一个字段存在大量的重复值时,不适合建立索引,比如之前举例的性别字段。(但是低选择性 数据有倾斜的可以 比如三个状态 原则上是大量重复的 但是如果有一种状态特别少一种状态特别多 那么也可以用索引(CBO自动优化))

❸索引不能参与计算,因此经常带函数查询的字段,并不适合建立索引。

❹一张表中的索引数量并不是越多越好,一般控制在3,最多不能超过5

❺建立联合索引时,一定要考虑优先级,查询频率最高的字段应当放首位。

❻当表的数据较少,不应当建立索引,因为数据量不大时,维护索引反而开销更大。

❼索引的字段值无序时,不推荐建立索引,因为会造成页分裂,尤其是主键索引。

虽然前八点不一定要遵守 但是后七点一定要避免

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/737337.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

火山引擎 DataLeap 套件下构建数据目录(Data Catalog)系统的实践

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 摘要 Data Catalog 产品&#xff0c;通过汇总技术和业务元数据&#xff0c;解决大数据生产者组织梳理数据、数据消费者找数和理解数的业务场景&#xff0c;并服务于…

【综述003】面向未来的语义通信:基本原理与实现方法

摘要 0.引言 张平&#xff1a;提出“智简&#xff08;Intellicise&#xff09;”理念&#xff0c;提出模型驱动的语义通信框架&#xff0c;实现通信系统由传统传输比特演进为传输“模型”。如&#xff1a;语义基&#xff08;Seb&#xff09;牛凯&#xff1a;研究了从经典通信…

Three.js 三维模型(一)

简介 今天主要给搭建介绍下three.js的基本使用&#xff0c;本篇是基于笔者在16年给做的一个项目的demo版进行讲解的&#xff0c;笔者当时采用Html5和JS进行编写的。可能大家会问有没有vue、React 、angular版的。这些笔者后面有时间的时候一定会给大家介绍。 其实编程的本源在…

牌桌玩家越来越少?国产替代进程加速,中国企业要做好选择

现在“国产替代”这四个字热度很高。 可以说我们现在关注的问题&#xff0c;技术引进、自主创新、中国制造、卡脖子、全球竞争等&#xff0c;都可以用国产替代作为线索串联起来&#xff01; 其实这也不是21世纪之后中国刚刚遇到的问题。这是过去一百年中国人一直在奋斗的目标…

机器人动力学与控制学习笔记(十七)——基于名义模型的机器人滑模控制

十七、滑模控制器设计原理 滑模运动包括趋近运动和滑模运动两个过程。系统从任意初始状态趋向切换面&#xff0c;直到到达切换面的运动称为趋近运动&#xff0c;即趋近运动为的过程。根据滑模变结构原理&#xff0c;滑模可达性条件仅保证由状态空间任意位置运动点在有限时间内到…

NLP领域再创佳绩!阿里云机器学习平台 PAI 多篇论文入选 ACL 2023

近期&#xff0c;阿里云机器学习平台PAI主导的多篇论文在ACL 2023 Industry Track上入选。ACL是人工智能自然语言处理领域的顶级国际会议&#xff0c;聚焦于自然语言处理技术在各个应用场景的学术研究。该会议曾推动了预训练语言模型、文本挖掘、对话系统、机器翻译等自然语言处…

Trimble RealWorks处理点云数据(九)之点云分类后将地面导入Arcgis生成DEM

效果 步骤 1、las导入Trimble RealWorks 2、对点云数据预处理 可以参考这篇文章 TrimbleRealWorks点云数据预处理 我这边是把点云做了分类,而后将地面数据导出las 点云做为三维数据,后续步骤在arcscene中操作,能实时显示出来 3、arcscene创建las数据集

【计算机视觉 | 图像分割】arxiv 计算机视觉关于图像分割的学术速递(7 月 10 日论文合集)

文章目录 一、分割|语义相关(6篇)1.1 Unsupervised Segmentation of Fetal Brain MRI using Deep Learning Cascaded Registration1.2 Tranfer Learning of Semantic Segmentation Methods for Identifying Buried Archaeological Structures on LiDAR Data1.3 To pretrain or …

Vue2----Uniapp自定义弹窗

对于擅长后端的程序员&#xff0c;在编写前端时常常回去找库&#xff0c;比如elementUI&#xff0c;uview之类&#xff0c;但是往往这些库较为冗杂&#xff0c;有些功能比较强大&#xff0c;基本用不到&#xff0c;不好理解。这时候&#xff0c;如果可以自定义组件可能会对开发…

C++ STL常见算法

目录 1 各种常见算法的用法 1.1 非可变序列算法 1.2 可变序列算法 1.3 Partitions 1.4 排序算法 1.5 查找算法 1.6 集合算法 1.7 堆算法 1.8 最大最小值算法 1.9 其他算法 1 各种常见算法的用法 STL算法部分主要由头文件<algorithm>,<numeric>,<func…

uniapp 获取状态栏及小程序右侧胶囊信息(用于设置全屏小程序)

1.获取信息: //获取状态栏高度(px) this.statusBarHeight uni.getSystemInfoSync().statusBarHeight; //获取小程序胶囊信息 this.menuButtonInfo uni.getMenuButtonBoundingClientRect() 如下: 2.动态设置style样式: <view:style"{ paddingTop: menuButtonIn…

Oracle-RAC集群安装root.sh报错问题

问题背景: 在redhat 7.8上安装Oracle11G RAC集群&#xff0c;在节点一执行root.sh脚本时发生错误Disk Group OCRDG creation failed with the following message:ORA-15018: diskgroup cannot be created 问题分析: 从报错信息来看错误是在执行创建OCRDG磁盘组时失败&#xff0…

Python读取指定的TXT文本文件并从中提取指定数据的方法

本文介绍基于Python语言&#xff0c;遍历文件夹并从中找到文件名称符合我们需求的多个.txt格式文本文件&#xff0c;并从上述每一个文本文件中&#xff0c;找到我们需要的指定数据&#xff0c;最后得到所有文本文件中我们需要的数据的合集的方法。 首先&#xff0c;我们来明确一…

进度网络图详解

关键路径&#xff1a;总工期最长的那一条路径&#xff1a;可能不止一条。&#xff08;1条或多条&#xff09; 虚工作&#xff1a;不占用任何时间和资源的&#xff0c;只是为了让逻辑关系更加明确&#xff0c;网络图更加美观。 最早开始时间&#xff08;ES&#xff09;- 左上 最…

BT 种子,磁力链接是个啥?

[科普向] BT 种子、磁力链接到底是什么&#xff1f; BitTorrent 我们平时所说的 BT 种子&#xff0c;实际上指的是由 BitTorrent 协议所生成的一个包含资源信息的文件。与传统的网络传输协议不同&#xff0c;BitTorrent 协议是一种以 Peer-To-Peer&#xff08;P2P&#xff09…

【KingbaseES】查看表空间大小

查询单表空间大小 SELECT sys_size_pretty(sys_tablespace_size(sys_default))查看所有表空间大小&#xff08;不包含系统表空间&#xff0c;包含默认表空间&#xff09; SELECT oid,spcname AS "Name",sys_size_pretty(sys_tablespace_size(spcname)) AS "Lo…

2. SpringBoot快速回顾(@value读取配置文件)

目录 1.定义配置文件2. 定义Controller类3. 测试4. 优化4.1 封装实体类4.3 定义controller类4.2 测试 本文将介绍如何使用value读取配置文件的内容。 在实际项目中&#xff0c;往往会在配置文件中写项目部署需要配置的环境信息&#xff08;数据库驱动&#xff0c;数据库账号密码…

mysql离线安装

MySQL离线安装 进行MySQL离线安装包,当前安装版本为MySQL8.0.32 下载页面&#xff1a;https://downloads.mysql.com/archives/community/ 下载地址&#xff1a;https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.36-1.el7.x86_64.rpm-bundle.tar 将下载完成的安…

【Linux】关于Linux系统挂载大于2TB磁盘的问题

之前在Linux系统挂载文件系统的时候&#xff0c;我已经习惯了使用 fdisk 命令来对磁盘进行分区。fdisk 常用的几个指令有&#xff1a; m 显示命令帮助菜单&#xff1b; n 创建新的分区&#xff1b; p 显示分区信息&#xff1b; t 修改分区类型&#xff08;一般设置为8e&…

Transformer原理理解

本文介绍Transformer的基本原理&#xff0c;主要记录一下自己的学习过程。 论文&#xff1a;https://arxiv.org/abs/1706.03762 参考&#xff1a; http://jalammar.github.io/illustrated-transformer/https://zhuanlan.zhihu.com/p/338817680https://blog.csdn.net/longxin…