SQL进阶理论篇(九):为什么不存在完美的索引

文章目录

  • 简介
  • 索引片和过滤因子
  • 如何通过宽表避免回表
  • 什么是过滤因子
  • 理想索引设计:三星索引
  • 为什么很难存在理想的索引设计?
  • 参考文献

简介

本节将主要介绍以下部分:

  • 什么是索引片,什么是过滤因子?
  • 设计索引的时候,可以遵循哪些原则
  • 为什么理想的索引很难应用在实际工作中?

索引片和过滤因子

索引片就是SQL查询语句在执行时需要扫描的一个索引片段,我们会根据索引片中包含的匹配列的数量的不同,将索引分为窄索引和宽索引。其中窄索引一般指包含索引列数为1或者2,宽索引一般指列数大于2。

如果索引片越宽,那么可能需要顺序扫描的索引页就越多;如果索引片越窄,在一定程度上就可以减少索引访问的开销。

比如,在product_comment表中,comment_id为主键,我们可以设置(user_id)为窄索引,也可以设置其他所有字段(user_id, product_id,comment_text)为宽索引。

如图:

在这里插入图片描述

需要说明的是,每个非聚集索引(二级索引)里都会保存主键值,然后通过主键值,去磁盘上回表来查找相应的记录行(二次操作,所以叫做二级索引)。因此每个索引都相当于包括了主键

所以我们在声明窄索引(user_id)的时候,其实就相当于声明了(comment_id,user_id)。我们声明宽索引(user_id, product_id,comment_text)时,就相当于声明了(comment_id,user_id, product_id,comment_text),覆盖了全表字段。

如何通过宽表避免回表

宽索引需要顺序扫描的索引页很多,但也是有好处的,在多数情况下,它可以不需要回表,直接从索引树里拿数据就可以(需要的字段都是索引)。

回表指的就是,数据库在根据索引找到了主键之后,还需要通过主键再次到数据表中去读取对应记录行的过程。

教程里举了个例子,来讲解使用不同的索引片来运行相同查询时的时间差异。

比如,先以窄索引(user_id)来执行下面语句:

SELECT comment_id, product_id, comment_text, user_id FROM product_comment WHERE user_id between 100001 and 100100

返回110条记录,耗时0.062s。

接着我们再以宽索引(user_id, product_id, comment_text)运行上面语句,结果相同,耗时为0.043s。

可以看到,查询效率会有一些提升。这就是因为select中需要的列都在宽索引里,数据库直接扫描索引树就可以,不需要再回表了,所以一定程度上提升了SQL查询的效率。

什么是过滤因子

在设计索引片的时候,我们还需要考虑一个辅助因素,就是过滤因子

过滤因子,描述了谓词的选择性。

什么是谓词呢?

在where条件语句中,每一个条件都称为一个谓词。因此谓词选择性,实际上就等于满足这个条件列的记录数除以总记录数的值。可以理解成满足条件的记录数比例。

比如说我们有一个player球员表,其中有team_id,height、name、gender等字段,然后gender的取值都是male。

接下来我们评估下这些过滤因子的筛选能力:

在这里插入图片描述

可以看到,gender和team_id都不是一个好的过滤因子,单值比例有些过于高了。相比之下,过滤因子筛选能力最强的,是name字段。

那如果我们创建一个联合过滤条件,如(height, team_id),它的过滤能力如图:

在这里插入图片描述

可以看到联合过滤因子的过滤性是很强的。

不过需要注意,在联合的时候,各组成条件的关联性应该尽量互相独立,如果列和列之间具有相关性,那么创造出来的联合过滤因子,过滤效果就会差很多。

因此,过滤因子实际上决定了索引片的大小,即索引片中的记录数。过滤因子的条件过滤能力越强,满足条件的记录数就越少,索引片也就越小。

理想索引设计:三星索引

在索引的设计里,确实存在一种规范,叫做三星索引规范,其在索引设计中的地位相当于3NF在数据表设计中的地位。

三星索引具体是指:

  • 在where条件语句中,找到所有等值谓词中的条件列,将它们作为索引片中的开始列;
  • 将group by和order by的列也加入索引;
  • 将select字段中剩余的列加入索引片。

如此下来,我们的索引片基本会变成一个宽索引,近乎涵盖了所有能添加的相关列。那么对于一条查询来说,这样做的效率是最高的码?

一般来讲,是的。

首先,将where中的等值谓词加入索引片,借助索引进行过滤,效率自然是高的。

其次,将group by和order by中的列也加入索引,可以有效避免进行file sort排序,因为创建了索引就会按照索引顺序来存储数据,二次分组或者排序的时候就会提升效率。

最后,select中列加入索引。好处更明显了,就是避免回表现象。所有的列都在索引树里了,还回表去读什么记录行?节省了IO,自然就快了。

为什么很难存在理想的索引设计?

三星索引设计这么高效,那是不是大家都用三星索引就可以了?

那当然不是,三星索引的缺点也很明显。主要有以下几点:

  • 索引片太宽了。一个索引片十几二十列,那么单个页能放的索引数据就少了,要读取相同数量的索引数据的话,就要去读更多的页,在极端情况下,很难说效率还会不会高。
  • 如果数据量过大,比如说成百上千万行,那么存储它们的索引,也需要占用很大的磁盘,而且这么多索引,带给缓冲池空间的压力也很大。
  • 索引维护的成本很高。当新数据进来的时候,就需要重构索引,当成百上千的数据进来呢?这个时间和计算资源的消耗是很大的。

因此,我们实际使用的时候,还是需要权衡的,而且大多数情况下,我们还是会像反范式设计一样,反三星式设计。

  • 单个表,索引不宜过多,否则增加/修改数据时,对索引的修改会造成额外的消耗。
  • 定期检查索引使用情况,对于使用频率低的索引,可以及时删除。
  • 控制索引片中的索引列数量。通常我们会把where中的条件列加入索引,而select里的不会。
  • 尽量使用数值类型代替字符类型来构建索引,避免使用字符类型做主键,对字符字段最好只建前缀索引。在 MySQL InnoDB 中,系统默认单个索引长度最大为 767 bytes,如果单列索引长度超过了这个限制,就会取前缀索引,也就是取前 255 字符。这实际上也是告诉我们,字符列会占用较大的空间

看到一条很有趣的评论,他说"所谓的三星索引,其实就是面向查询建了个表"。哈哈哈哈哈哈,我觉得他说的很有道理。

参考文献

  1. 29丨为什么没有理想的索引?

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1847_MOSFET预驱以及作用

Grey 全部学习内容汇总:GitHub - GreyZhang/g_hardware_basic: You should learn some hardware design knowledge in case hardware engineer would ask you to prove your software is right when their hardware design is wrong! 1847_MOSFET预驱以及作用 MO…

5分钟部署你的第一个K8S应用

查看k8s集群信息 kubectl cluster-info查看节点信息 kubectl get node查看内部组件 kubectl get pod -A部署第一个K8S应用-Nginx,并通过公网ip访问 创建deployment(Pod控制器的一种, 直接删除pod后,会自动创建新的,需要删除de…

黑马头条--day02.文章列表查看

目录 一.分表 1.导入数据库sql脚本 2.导入实体类 3.分表规则 二.文章列表接口 (1)思路 2)接口定义 3)功能实现 1.1):导入heima-leadnews-article微服务,资料在当天的文件夹中 1.2):定义接口 1.3):编写mapper文件 1.4)&…

Support Vector Machine(SVM)——支持向量机

1.从逻辑回归到SVM 回顾一下逻辑回归的模型 然后经过sigmoid函数得到预测y1的概率,sigmoid函数如下图 对于单个样本来说损失函数如下 当一个输入的真实标签为1时,损失函数就只剩,如左图所示,我们想要让,来使损失函数尽可能的小 对…

重新认识Word——尾注

重新认识Word——尾注 参考文献格式文献自动生成器插入尾注将数字带上方括号将参考文献中的标号改为非上标 多处引用一篇文献多篇文献被一处引用插入尾注有横线怎么删除?删除尾注 前面我们学习了如何给图片,公式自动添加编号,今天我们来看看毕…

【TB作品】51单片机读取重量和液位,OLED显示

代码打开下载: http://dt4.8tupian.net/2/28880a64b6666.pg3这段代码是为微控制器编写的,可能是基于8051架构,使用Keil C51编译器。该代码结合了OLED显示器、超声波距离传感器和基于HX711的称重传感器的功能。以下是主要组件及其功能的详细说…

海洋可视化大屏,Photoshop源文件

数据大屏通过实时的数据展示,可及时发现数据的变化和异常,以便及时采取措施。现分享海洋动力大数据监控、海洋数据监控系统、科技感海洋监控系统大屏模版的UI源文件,供UI设计师们快速获取PSD源文件完成工作 若需更多 大屏组件,请…

1852_bash中的find应用扩展

Grey 全部学习内容汇总: https://github.com/GreyZhang/toolbox 1852_bash中的find应用扩展 find这个工具我用了好多年了,但是是不是真的会用呢?其实不然,否则也不会出现这种总结式的笔记。其实,注意部分小细节之后…

电子学会C/C++编程等级考试2021年09月(六级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:双端队列 定义一个双端队列,进队操作与普通队列一样,从队尾进入。出队操作既可以从队头,也可以从队尾。编程实现这个数据结构。 时间限制:1000 内存限制:65535输入 第一行输入一个整数t,代表测试数据的组数。 每组数据的…

国内最好的开源MES/免费MES/低代码MES

一、系统概述: 万界星空科技免费MES、开源MES、商业开源MES、市面上最好的开源MES、MES源代码、适合二开的开源MES、功能最全的开源MES、好看的数字大屏、开源自动排班系统、开源质检系统。 1.万界星空开源MES制造执行系统的Java开源版本。 开源mes系统包括系统管…

re:Invent2023大会隆重推出自研芯片Graviton4和Trainium2

目录 一、前言 二、体验Graviton系列产品 (一)创建普通的EC2实例 (二)创建Graviton处理器的EC2实例 (三)远程到服务器 方式1:创建成功时连接 方式2:SSH客户端 方式3:正确…

01--二分查找

一. 初识算法 1.1 什么是算法? 在数学和计算机科学领域,算法是一系列有限的严谨指令,通常用于解决一类特定问题或执行计算 不正式的说,算法就是任何定义优良的计算过程:接收一些值作为输入,在有限的时间…

【LeetCode:746. 使用最小花费爬楼梯 | 递归 -> 记忆化搜索 -> DP】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

Python基础08-文件操作详解

零、文章目录 Python基础08-文件操作详解 1、文件操作概述 (1)文件是什么 内存中存放的数据在计算机关机后就会消失。要长久保存数据,就要使用硬盘、光盘、U 盘等设备。为了便于数据的管理和检索,引入了**“文件”**的概念。 …

【普中】基于51单片机简易计算器显示设计( proteus仿真+程序+设计报告+实物演示+讲解视频)

目录标题 📟1. 主要功能:📟2. 讲解视频:📟3. 设计说明书(报告)📟4. 仿真📟5. 实物烧录和现象📟6. 程序代码📟7. 设计资料内容清单 【普中开发板】基于51单片机简易计算器…

nodejs+vue+微信小程序+python+PHP校园二手交易系统的设计与实现-计算机毕业设计推荐

(2)管理员 进行维护,以及平台的后台管理工作都依靠管理员,其可以对信息进行管理。需具备功能有;首页、个人中心、学生管理、物品分类管理、物品信息管理、心愿贴、系统管理、订单管理等功能。系统分成管理员控制模块和学生模块。 本系统有良好…

Source Insight使用

之前一直使用VS code阅读kernel源码,有时候函数跳转有些问题。最近换成了Source Insight软件,发现真不错。就是需要一些学习成本,简单记录一下如何使用吧。 1、下载安装: 首先肯定是要下载安装,这个就不写了&#xf…

Restrict Content Pro WordPress – 限制会员内容 付费内容网站(包含所有扩展)

Restrict Content Pro WordPress限制会员内容专业插件 强大的内容限制工具和强大的 WordPress 会员网站,都在一个易于管理的插件中。 购买Restrict Content Pro 最新版本并加入超过23000 名快乐客户的俱乐部。 使用 Restrict Content Pro 插件将您的独家内容锁定…

oracle怎么导入dmp文件??????

目录 oracle怎么导入dmp文件?????? 先看: 方法一:【推荐】 winR输入 输入: 检验: 导入成功! 方法二: 直接在 PLSQL Developer…