MySQL索引_什么是索引_索引的分类_什么时候需要/不需要创建索引_优化索引_索引失效

news2024/11/17 22:44:28

文章目录

    • 索引
      • 1. 什么是索引
      • 2. 索引的分类
        • 按数据结构分类
        • 按物理存储分类
        • 按字段特性分类
        • 按字段个数分类
      • 3. 什么时候需要 / 不需要创建索引?
        • 什么时候适用索引?
        • 什么时候不需要创建索引?
      • 4. 优化索引的方法
        • 前缀索引优化
        • 覆盖索引优化
        • 主键索引最好是自增的
        • 索引最好设置为NOT NULL
        • 防止索引失效

在这里插入图片描述

索引

1. 什么是索引

帮助存储引擎快速获取的数据的一种数据结构,是数据的目录,以空间换时间

2. 索引的分类

按数据结构分类

B+ Tree索引、HASH索引、Full-Text索引

  • 有主键,默认使用主键作为聚簇索引的索引键
  • 没有主键,选择第一个不包含NULL值的唯一列作为聚簇索引的索引键
  • 上面两个都没有的情况下,自动生成一个隐式自增id列作为…
  • 其他索引都属于辅助索引(二级索引、非聚簇索引)
  • 创建的主键索引和二级索引默认属于B+ Tree索引

例:

CREATE TABLE `product`  (
  `id` int(11) NOT NULL,
  `product_no` varchar(20)  DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `price` decimal(10, 2) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
(id为主键)

主键索引的B+ Tree:

叶子节点存放数据,非叶子节点只存放索引,每个节点里的数据按主键顺序存放。每一个叶子节点有两个指针,分别指向下一个叶子节点和上一个叶子节点,形成双向链表

主键索引 BTree

数据库的索引和数据都存在硬盘,读取一个节点当作一次磁盘I/O操作。B+ Tree存储千万级数据只需要3-4层高度,即最多需要3-4次磁盘I/O。查询效率很高。

二级索引的B+ Tree:

叶子节点存放的是主键值,而不是实际数据

(将product_no设置为二级索引)

二级索引 BTree

用二级索引查询数据:

select * from product where product_no = '0002';

找到对应的叶子节点,获取主键值,再通过主键索引的B+Tree树查询到对应的叶子节点,获取整行数据。称为回表,需要两个B+ Tree才能查到数据

select id from product where product_no = '0002';

查询的数据在二级索引的B+ Tree的叶子节点里查询到,不用再查主键索引再查。称为覆盖索引,只需要查一个B+ Tree

为什么mysql innoDB 选择 B+ tree作为索引的数据结构?

  1. B+ Tree vs B Tree

  2. B树的非叶子节点也要存储数据,所以B+树的单个节点的数据量更小,相同的磁盘I/O次数下,就能查询到更多的节点

  3. B+树的叶子节点采用双链表连接,B树做不到

  4. B+ Tree vs 二叉树

  5. B+Tree的搜索复杂度:O(logdN),d表示节点允许的最大子节点的个数

  6. 二叉树的搜索复杂度:O(log2N)

  7. 二叉树检索到目标数据所经历的磁盘I/O次数更多

  8. B+ Tree vs Hash

  9. Hash在做等值查询时,搜索复杂度O(1),不适合做范围查询

按物理存储分类

聚簇索引(主键索引),二级索引(辅助索引)

  • 主键索引的叶子节点存放实际数据
  • 二级索引的叶子节点存放主键值
    • 如果查询的数据能在二级索引里查询到,则为覆盖索引
    • 如果查询的数据在二级索引里查询不到,需要先检索二级索引,找到对应叶子节点获取到主键值后,再检索主键索引,查询到数据,则为回表
按字段特性分类

主键索引、唯一索引、普通索引、前缀索引

  • 主键索引

    • 建立在主键字段上的索引,一张表最多只有一个主键索引,索引列不允许有空值

    • CREATE TABLE table_name(
          ...
          PRIMARY KEY(index) USING BTREE
      )
      
  • 唯一索引

    • 建立在UNIQUE字段上的索引,一张表可以有多个唯一索引,索引列的值必须唯一,允许有空值

    • CREATE TABLE table_name(
          ...
          UNIQUE KEY(index1,index2...)
      )
      
    • CREATE UNIQUE INDEX index_name ON table_name(index_column_1,index_column_2,...); 
      
  • 普通索引

    • 建立在普通字段上的索引

    • CREATE TABLE table_name(
          ...
          INDEX(index1,index2...)
      )
      
    • CREATE INDEX index_name ON table_name(index_column_1,index_column_2,...); 
      
  • 前缀索引

    • 对字符类型字段的前几个字符建立索引,而不是整个字段上建立的索引。(可以建立在字段类型为char varchar binary varbinary的列上)

    • 减少索引占用的存储空间,提升查询效率

    • CREATE TABLE table_name(
          ...
          INDEX(column_name(length))
      )
      
    • CREATE INDEX index_name ON table_name(column_name(length))
      
按字段个数分类
  • 单列索引

    • 建立在单列上的索引称为单列索引,比如:主键索引
  • 联合索引(复合索引)

    • 建立在多列上的索引称为联合索引

    • CREATE INDEX index_product_no_name ON product(product_no, name);
      
    • 联合索引的B+树联合索引

    • 非叶节点用两个字段的值作为key值,在联合索引查询数据时,先按prodcut_no字段比较,相同的情况下再按name字段排序

    • 叶子节点保存主键值

    • 使用联合索引时,存在最左匹配原则

      • 例:创建了(a,b,c)联合索引

      • 1. 可以使用联合索引(有查询优化器,a字段的顺序不重要)
            where a=1;
            where a=1 and b=2 and c=3;
            where a=1 and b=2;
        2. 联合索引失效
            where b=2;
            where c=3;
            where b=2 and c=3;
            因为b和c是全局无序,局部有序
        
      • 例:a,b联合索引的B+ Treeimg

      • 注意到a是全局有序的,b是全局无序的,所以直接执行where b = 2这种查询条件没法使用联合索引,利用索引的前提是索引里的key是有序的

    • 联合索引范围查询

      • 并不是查询过程使用了联合索引就代表所有字段使用了联合索引进行索引查询 => 发生在范围查询(范围查询的字段可以使用到联合索引,但是范围查询字段后面的字段无法使用到联合索引)

      • 例:

        1. Q1: select * from t_table where a > 1 and b = 2,联合索引(a, b)哪一个字段用到了联合索引的 B+Tree?
                a字段
                联合索引先按a字段值排序,所以a>1的记录一定是相邻的。但符合a>1条件的二级索引记录的范围里,b字段的值无序。
        2. Q2: select * from t_table where a >= 1 and b = 2,联合索引(a, b)哪一个字段用到了联合索引的 B+Tree?
                a和b
                与1不同的是,a的查询条件是大于等于
                虽然在符合a>=1的二级索引记录的范围里,b字段是无序的,但是a=1时,b字段是有序的
                从符合 a = 1 and b = 2 条件的第一条记录开始扫描,而不需要从第一个 a 字段值为 1 的记录开始扫描。
        3. Q3: SELECT * FROM t_table WHERE a BETWEEN 2 AND 8 AND b = 2,联合索引(a, b)哪一个字段用到了联合索引的 B+Tree?
                a和b
                mysql中between包含了边界值,类似于>= <=,所以类似于Q2查询语句。
        4. Q4: SELECT * FROM t_user WHERE name like 'j%' and age = 22,联合索引(name, age)哪一个字段用到了联合索引的 B+Tree?
        

        img

        4. 
                a和b
                j相等时,age字段有序,即从符合 name = 'j' and age = 22 条件的第一条记录时开始扫描,而不需要从第一个 name 为 j 的记录开始扫描 
        
      • 综上所述,联合索引的最左匹配原则,在遇到范围查询为> < 时,会停止匹配。对于>= <= BETWEEN like前缀匹配的范围查询,不会停止匹配

    • 索引下推

      • select * from table where a > 1 and b = 2
        
      • 找到第一个满足条件的主键值后,判断b是否=2,在联合索引里判断,还是回主键索引判断?

      • mysq5.6之前,只能回表,回到主键索引找到数据行,对比b字段值

      • 5.6之后引入索引下推优化,在联合索引遍历过程中,对联合索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数

    • 索引区分度

      • 在建立联合索引时,要把区分度大的字段排在前面,越有可能被更多的sql使用
      • 区分度计算公式:某个字段column不同值的个数/表的总行数
      • 如果索引区分度很小,不如不要索引
    • 联合索引进行排序

      • select * from order where status = 1 order by create_time asc
        
      • 可以使用status和create_time建立联合索引,可以避免mysql数据库发生文件排序(如果只用到 status 的索引,但是这条语句还要对 create_time 排序,这时就要用文件排序 filesort),提高查询效率

3. 什么时候需要 / 不需要创建索引?

索引的好处:提高查询速度

缺点:占用物理空间、创建和维护要耗费时间、降低表的增删改的频率(增删改后要进行维护)

什么时候适用索引?
  • 字段有唯一性限制,比如商品编码
  • 经常用于WHERE查询的字段
  • 经常用于GROUP BY 和 ORDER BY的字段,查询时不需要再做排序
什么时候不需要创建索引?
  • where条件,group by,order by用不到的字段
  • 字段中存在大量重复数据(见区分度)
  • 表数据太少
  • 经常更新的字段

4. 优化索引的方法

前缀索引优化

使用某个字段中字符串的前几个字符建立索引,减少索引字段大小

增加一个索引页中存储的索引值,有效提高索引的查询速度

缺点:

  • order by无法使用前缀索引
  • 无法把前缀索引用作覆盖索引
覆盖索引优化

覆盖索引:查询的所有字段,在索引B+树的叶子节点上都能找得到的索引。从二级索引中查询得到记录,不需要回表

例:只需要查询商品的名称、价格,什么方式避免回表?

​ 建立(商品ID、名称、价格)联合索引

主键索引最好是自增的
  • 使用自增主键
    • 每次插入的新数据就会按顺序添加到当前索引节点的位置,不需要移动已有数据,页面写满,就会自动开辟一个新页面
    • 插入一条新纪录,都是追加操作,不需要重新移动数据
  • 使用非自增主键
    • 每次插入新数据时,有可能插入到现有数据页中间的某个位置,不得不移动其他数据来满足新数据的插入,甚至需要从一个页面复制数据到另一个页面=>页分裂,还有可能造成大量的内存碎片,导致索引结构不紧凑,从而影响查询效率
  • 主键的长度不要太大,因为主键的长度越小,意味着二级索引的叶子节点越小(二级索引的叶子节点存放的数据是主键值),这样二级索引占用的空间也越小
索引最好设置为NOT NULL
  • 为NULL会导致优化器在做索引选择时更加复杂,难以优化
  • NULL值无意义,但是会占用物理空间(NULL值列表)
防止索引失效

避免写出索引失效的查询语句,否则查询效率很低

发生索引失效的情况:

  • 使用左/左右模糊匹配时,like %xx like %xx%

  • 在查询条件中对索引列做了计算、函数、类型转换操作

  • 联合索引要能正确使用需要遵循最左匹配原则

  • where子句中,如果or前的列是索引列,or后的不是索引列,那么索引会失效

  • 其他索引失效的场景可以查看执行计划 explain ...

    • type字段:表示数据扫描类型

      • ALL:全表扫描

        • 最坏情况
      • index:全索引扫描

        • 和全表扫描差不多,对索引表进行全扫描
      • range:索引范围扫描

        • 一般在使用< > in between时
      • ref:非唯一索引扫描

        • 索引是有序的,即便有重复值,也是在很小的范围内扫描
      • eq_ref:唯一索引扫描

        • 使用主键/唯一索引时产生,通常使用在多表联查中
        • 例如,两张表进行联查,关联条件是user_id相等,且user_id是唯一索引
      • const:结果只有一条的主键/唯一索引扫描

        • 例如,select name from product where id = 1
        • 与eq_ref不同的是:与常量进行比较,查询效率更快。eq_ref通常用于多表联查

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

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

相关文章

迅腾文化助力企业品牌创新,加快增强品牌发展新动能

迅腾文化助力企业品牌创新&#xff0c;加快增强品牌发展新动能 随着市场竞争的日益激烈&#xff0c;品牌创新已成为企业持续发展的关键。为了在市场中脱颖而出&#xff0c;许多企业纷纷寻求外部合作伙伴以加快品牌发展。广州迅腾文化传播有限公司拥有13年品宣经验的企业&#…

迪文屏图标控件保姆级教程

要主图的去末尾&#xff0c;末尾福利图在等着你~~~ 文章目录 前言 开发环境 二、使用步骤 1.添加图标控件 2.设置图标属性 3.图标库ICL文件生成 4.单片机程序编写 容易踩得坑 一、前言 本篇文章主要介绍了在DGBUS平台上使用图标变量的步骤。首先需要在DGBUS中添加一个图标变量控…

【教学类-35-07】正方形折纸上的学号描字帖(15*15CM1份)

背景需求&#xff1a; 尝试将加减法题目打印在手工纸上&#xff0c;写完书写题后&#xff0c;反面绘画&#xff0c;最后折纸。 用同样的思路&#xff0c;在15*15CM正方形手工纸上做一套幼儿学号描字帖 素材准备 WORD模板&#xff08;纸张长宽15*15CM&#xff0c;边距上下左右0&…

【源码解析】从Conditon角度聊聊AQS原理

前几篇文章&#xff0c;我们详细描述了线程池的原理以及核心代码&#xff0c;以及阻塞队列&#xff0c;ReentrantLock的核心流程&#xff0c;本篇主要介绍下lock锁中的condition 公平锁和非公平锁 public ReentrantLock() {sync new NonfairSync();}public ReentrantLock(boo…

Liunx系统挂载磁盘

1.具体步骤 大概五个步骤 添加磁盘磁盘分区格式化分区挂载分区到指定目录设置开机自动挂载 目标将sdb1分区挂载到/data目录 2.添加磁盘 使用lsblk -f命令可以查看当前系统磁盘情况 lsblk -f 可以看到已经有一个磁盘sda&#xff0c;现在我们给虚拟机增加一个磁盘 添加完成后…

五、Java核心数组篇

1.数组 概念&#xff1a; ​ 指的是一种容器&#xff0c;可以同来存储同种数据类型的多个值。 ​ 但是数组容器在存储数据的时候&#xff0c;需要结合隐式转换考虑。 比如&#xff1a; ​ 定义了一个int类型的数组。那么boolean。double类型的数据是不能存到这个数组中的&…

什么台灯好用不伤眼睛?适合考公使用的台灯推荐

随着时代的发展与进步&#xff0c;不管是办公族还是学生党的压力也越来越大的&#xff0c;不少人在晚上回去之后仍然需要学习、工作&#xff0c;这样的一件试几乎成为了“家常便饭”&#xff0c;而这个过程中必不可少就是台灯。有些人为了保护眼睛会选择护眼台灯&#xff0c;但…

考研护眼台灯怎么选好?2023考研党台灯分享

现在随着生活水平的提升&#xff0c;孩子的教育也越好越好了&#xff0c;不过随之而来的就是繁重的学习压力&#xff0c;和做不完的作业。细心的家长可能已经发现&#xff0c;自从孩子步入高年级之后&#xff0c;晚上回到家完成作业的时间也越来越长了&#xff0c;这不得不让身…

OfficeWeb365 SaveDraw 文件上传漏洞复现

0x01 产品简介 OfficeWeb365 是专注于 Office 文档在线预览及PDF文档在线预览云服务,包括 Microsoft Word 文档在线预览、Excel 表格在线预览、Powerpoint 演示文档在线预览,WPS 文字处理、WPS 表格、WPS 演示及 Adobe PDF 文档在线预览。 0x02 漏洞概述 OfficeWeb365 Sav…

面相对象开发的原则

1、开闭原则 对修改关闭&#xff0c;对扩展打开。 2、里氏替换原则 子类继承父类的方法时&#xff0c;不可重写父类的方法。 如果重写了父类的方法会导致整个继承体系比较差&#xff0c;特别是运用多态比较平凡时&#xff0c;程序运行出错概率较大。 如果出现了违背“里氏替换…

力扣105与106从前序与中序(中序与后序)遍历序列构造二叉树

本题刚接触时比较懵&#xff0c;做出来后就很好理解。之前数据结构的题&#xff1a;给出中序与后序&#xff08;或前序与中序&#xff09;画出该树 无从下笔不知如何去画&#xff0c;做完此题后就发现豁然开朗&#xff0c;不过尔尔。本题只讲中序与后序&#xff08;前序与中序一…

【设计模式--行为型--命令模式】

设计模式--行为型--命令模式 命令模式定义结构案例优缺点使用场景 命令模式 定义 将一个请求封装为一个对象&#xff0c;使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通&#xff0c;这样方便将命令对象进行存储&#xff0c;传递&#xff0c;调用…

cpp:1:10: fatal error: opencv2/core.hpp: 没有那个文件或目录

前言&#xff1a; 我按照官网方法安装了opencv&#xff0c;运行的也是官网的测试代码&#xff1a; #include <opencv2/core.hpp> #include <opencv2/highgui.hpp> using namespace cv; int main() {printf("hello world")return 0; } 半解决&#xff…

TCP/IP详解——TCP 协议

文章目录 一、传输层协议1. TCP1.1 TCP 的字节流1.2 TCP 端口号1.3 TCP 头部1.4 TCP 选项部分字段1.5 TCP 三次握手1.6 TCP 三次握手不成功1.6.1 TCP 拒绝&#xff08;被RST重置&#xff09;1.6.2 TCP 半连接1.6.3 TCP 连接无响应 1.7 TCP 传输过程及原理1.7.1 TCP 传输过程1.7…

高通开发系列 - 功耗问题之添加CPU Idle和Hotplug的功能

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 返回:专栏总目录 目录 概述CPU IdleCPU TopologyCPU Idle DriverCPU Idle GovernorCPU的hotplug函数

给我说说Redis持久化机制RDB吧

基础 了解过Redis持久化RDB嘛&#xff1f;可不可以解释一下什么是RDB。 答&#xff1a; RDB持久化机制是将内存中的数据生成快照并持久化到磁盘的过程&#xff0c;RDB可以通过手动或者自动的方式实现持久化。 那RDB触发的方式有哪几种方式知道吗&#xff1f; 答: 有两种&am…

【Go】基于GoFiber从零开始搭建一个GoWeb后台管理系统(三)日志管理(登录日志、操作日志)、用户登录模块

第一篇&#xff1a;【Go】基于GoFiber从零开始搭建一个GoWeb后台管理系统&#xff08;一&#xff09;搭建项目 第二篇&#xff1a;【Go】基于GoFiber从零开始搭建一个GoWeb后台管理系统&#xff08;二&#xff09;日志输出中间件、校验token中间件、配置路由、基础工具函数。 …

赛氪为第五届全球校园人工智能算法精英大赛决赛选手保驾护航

12月10日&#xff0c;以“智青春算未来”为主题的2023年第五届全球校园人工智能算法精英大赛全国总决赛在河海大学江宁校区举行。本次大赛由江苏省人工智能学会主办&#xff0c;自9月份启动以来&#xff0c;共吸引了全国近400所高校的3000多支参赛团队参加。经过校赛、省赛选拔…

Linux(统信UOS) 发布.Net Core,并开启Https,绑定证书

实际开发中&#xff0c;有时会需要为小程序或者需要使用https的应用提供API接口服务&#xff0c;这就需要为.Net Core 配置https&#xff0c;配置起来很简单&#xff0c;只需要在配置文件appsettings.json中添加下面的内容即可 "Kestrel": {"Endpoints": …

LeetCode力扣每日一题(Java)66、加一

每日一题在昨天断开了一天&#xff0c;是因为作者沉迷吉他&#xff0c;无法自拔……竟然把每日一题给忘了&#xff0c;所以今天&#xff0c;发两篇每日一题&#xff0c;把昨天的给补上 一、题目 二、解题思路 1、我的思路 其实乍一看这道题还是比较简单的&#xff0c;就是让…