什么是前缀索引?

一、什么是前缀索引?

所谓前缀索引,说白了就是对文本的前几个字符建立索引( 具体是几个字符在建立索引时去指定),比如以产品名称的前 10 位来建索引,这样建立起来的索引更小,查询效率更快!

有点类似于 Oracle 中对字段使用 Left 函数来建立函数索引,只不过 MySQL 的这个前缀索引在查询时是内部自动完成匹配的,并不需要使用 Left 函数。

二、为什么要用前缀索引?

可能有的同学会发出疑问,为什么不对整个字段建立索引呢?

一般来说,当某个字段的数据量太大,而且查询又非常的频繁时,使用前缀索引能有效的减小索引文件的大小,让每个索引页可以保存更多的索引值,从而提高了索引查询的速度。

比如,客户店铺名称,有的名称很长,有的很短,如果完全按照全覆盖来建索引,索引的存储空间可能会非常的大, 有的表如果索引创建的很多,甚至会出现索引存储的空间都比数据表的存储空间大很多,因此对于这种文本很长的字段,我们可以截取前几个字符来建索引,在一定程度上,既能满足数据的查询效率要求,又能节省索引存储空间。

但是另一方面,前缀索引也有它的缺点,MySQL 中无法使用前缀索引进行 ORDER BY 和 GROUP BY,也无法用来进行覆盖扫描,当字符串本身可能比较长,而且前几个字符完全相同,这个时候前缀索引的优势已经不明显了,就没有创建前缀索引的必要了。

因此这又回到一个概念,那就是关于 索引的选择性

关于数据库表索引的选择性,我会单独开篇来讲解,大家只需要记住一点: 索引的选择性越高则查询效率越高,因为选择性高的索引可以让 MySQL 在查找时过滤掉更多的行,数据查询速度更快!

当某个字段内容的前几位区分度很高的时候,这个时候采用前缀索引,可以在查询性能和空间存储方面达到一个很高的性价比

那么问题来了,怎么创建前缀索引呢?

三、怎么创建前缀索引?

建立前缀索引的方式,方法很简单,通过如下方式即可创建!

ALTER TABLE table_name ADD KEY(column_name(prefix_length));

其中 prefix_length这个参数,就是前缀长度的意思,通常通过如下方式进行确认,步骤如下:

第一步,先计算某字段全列的区分度。

SELECT COUNT(DISTINCT column_name) / COUNT(*) FROM table_name;

第二步,然后再计算前缀长度为多少时和全列的区分度最相似

SELECT COUNT(DISTINCT LEFT(column_name, prefix_length)) / COUNT(*) FROM table_name;

最后,不断地调整 prefix_length的值,直到和全列计算出区分度相近,最相近的那个值,就是我们想要的值。

下面以某个测试表为例,数据体量在 100 万以上,表结构如下!

CREATE TABLE tb_test (
  id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  name varchar(100) DEFAULT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

什么是前缀索引?

什么是前缀索引?

测试一下正常的带 name条件查询,效率如下:

select * from tb_test where name like '1805.59281427%'

什么是前缀索引?

什么是前缀索引?

我们以 name 字段为例,创建前缀索引,找出最合适的 prefix_length

首先,我们大致计算一下 name字段全列的区分度。

什么是前缀索引?

可以看到,结果为 0.9945,也就是说全局不相同的数据率在 99.45%这个比例。

下面我们一起来看看,不同的 prefix_length值下,对应的数据不重复比例。

  • prefix_length5,区分度为 0.2237

什么是前缀索引?
  • prefix_length10,区分度为 0.9944

什么是前缀索引?
  • prefix_length11,区分度为 0.9945

什么是前缀索引?

通过对比,我们发现当 prefix_length11,最接近全局区分度,因此可以为 name创建一个长度为 11的前缀索引,创建索引语句如下:

alter table tb_test add key(name(11));

下面,我们再试试上面那个语句查询!

什么是前缀索引?

创建前缀索引之后,查询效率倍增

四、使用前缀索引需要注意的事项?

是不是所有的字段,都适合用前缀索引呢?

答案显然不是,在上文我们也说到了,当某个索引的字符串列很大时,创建的索引也就变得很大,为了减小索引体积,提高索引的扫描速度,使用索引的前部分字符串作为索引值,这样索引占用的空间就会大大减少,并且索引的选择性也不会降低很多,这时前缀索引显现的作用就会非常明显,前缀索引本质是索引查询性能和存储空间的一种平衡。

对于 BLOB 和 TEXT 列进行索引,或者非常长的 VARCHAR 列,就必须使用前缀索引,因为 MySQL 不允许索引它们的全部长度。

但是如果某个字段内容,比如前缀部分相似度很高,此时的前缀索引显现效果就不会很明显,采用覆盖索引效果会更好!

五、小结

好了,本文主要围绕前缀索引做了一次初步的知识讲解,具体数据库表索引的选择性,还需要结合业务实际需求来考虑!

今天就说这么多,后面的问题,我们继续再扯!

六、参考

1、CSDN – Java架构设计 – 一篇文章弄懂前缀索引

2、知乎 – Java编程宇宙 – 什么是前缀索引

Original: https://www.cnblogs.com/dxflqm/p/16745114.html
Author: 程序员志哥
Title: 什么是前缀索引?

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/594197/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • CentOS7下FTP的安装与配置2

    1、安装 yum install -y vsftpd 2、配置FTP 3、建立用户文件 4、生成用户加密数据 5、修改 /etc/pam.d/vsftpd 文件 6、新建系统用户t…

    Java 2023年5月29日
    075
  • .Net MVC实现角色-API权限验证的一种方式

    阅文时长 | 1.15分钟字数统计 | 1844.8字符主要内容 | 1、引言&背景 2、部分设计分享 3、声明与参考资料『.Net MVC实现角色-API权限验证的一种方…

    Java 2023年6月5日
    0103
  • spring上传文件

    本文将说明spring上传文件如何配置,以及从request请求中解析到文件流的原理 #添加依赖 主要用来解析request请求流,获取文件字段名、上传文件名、content-ty…

    Java 2023年6月9日
    079
  • IDEA自带UML插件在Java项目中无法显示依赖项

    可以进行设置,来避免显示一些不必要的线 看别人的IDEA可以显示类间的依赖项,而我的”显示依赖项”按钮点破都没用多次搜索无果(用Bing国内版),直到尝试用…

    Java 2023年6月5日
    087
  • SpringMVC的文件上传下载,异常处理,拦截器的小总结

    文件的上传和下载 我们通常在访问网页时会使用到文件的上传与下载的功能,那么他是如何实现的呢? ResponseEntity :用于控制器方法的返回值类型,该控制器方法的返回值就是响…

    Java 2023年6月8日
    058
  • Java基础语法(三)

    Java基础语法(三) 不积跬步,无以至千里;不积小流,无以成江海。 ——荀子《劝学》 Java基础语法(三) – 十六、方法 十七、命令行传参(扩展) 十八、可变参数…

    Java 2023年6月9日
    076
  • 亿级消息中心架构方案概述【原创】

    目标 技术目标: 上行到消息队列api吞吐量10000条/秒,下发第三方平台1000条/秒(仅平台自身处理能力,第三方看第三方处理能力极限指标为准);保证消息中心100%高可用。 …

    Java 2023年6月8日
    067
  • 搭建SpringCloud Alibaba鉴权中心服务(详细教程)

    鉴权中心服务 认识JWT json web token 是一个开放的标准 ,它定义了一个种紧凑的,自包含的方式,用于作为json对象在各方之间安全的传输信息 服务器鉴权完成之后 会…

    Java 2023年6月5日
    076
  • 《Apache RocketMQ 深入浅出》系列文章

    Apache RocketMQ是一个纯Java、分布式、队列模型的开源消息中间件,前身是MetaQ,是阿里参考Kafka特点研发的一个队列模型的消息中间件,后开源给apache基金…

    Java 2023年5月29日
    066
  • springboot jpa—->总结一下遇到的问题

    Native Query throw exception dto code import lombok.Value; @Value public class IdsOnly { I…

    Java 2023年5月30日
    066
  • 【每天学一点-04】使用脚手架搭建 React+TypeScript+umi.js+Antd 项目

    一、使用脚手架搭建项目框架 1、首先使用脚手架搭建React项目(React+TypeScript+Umi.js) 在控制台输入命令:yarn create @umijs/umi-…

    Java 2023年6月5日
    091
  • Nginx 源码分析– 内存池(pool)的分析 一

    Nginx内存池(pool)的管理的实现主要写在ngx_palloc.c这个文件中,为了明晰的看该文件中的函数之间的关系,我们描绘出以下一张简单的示意图: 图1 Nginx内存池(…

    Java 2023年6月15日
    078
  • 基于MybatisPlus代码生成器(2.0新版本)

    一、模块简介 1、功能亮点 实时读取库表结构元数据信息,比如表名、字段名、字段类型、注释等,选中修改后的表,点击 一键&#x75…

    Java 2023年6月6日
    079
  • springboot分析——与其他组件的整合(druid/mybatis)

    springboot本身提供了许多自动配置,帮助开发者提供开发效率,当然如果我们有一些个性化的需求,springboot 也提供了良好的扩展,只需要配置starter依赖或者简单的…

    Java 2023年5月30日
    057
  • FastAPI+pydantic+SQLAlchemy返回多个数据

    问题 比如在ORM中查询 all, 那么使用 pydantic.from_orm获取对应的数据呢? 解决思路 只需要, 将一个字段对应为 List, 元素为对应 SQLAlchem…

    Java 2023年6月7日
    056
  • 【一知半解】synchronied

    synchronized是什么 synchronized是java同步锁,同一时刻多个线程对同一资源进行修改时,能够保证同一时刻只有一个线程获取到资源并对其进行修改,因此保证了线程…

    Java 2023年6月9日
    067
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球