MYSQL索引的分类和创建

news2025/3/1 0:24:01

目录

1、聚簇索引和非聚簇索引

tips:

小问题:主键为什么建议使用自增id?

 2、普通索引 (常规索引)(normal)

3、唯一索引(UNIQUE )

唯一索引和主键的区别:

唯一约束和唯一索引的区别:

4、多个二级索引的组合使用!

5、复合索引(联合索引)!

6、全文索引(FULLTEXT)

7、hash索引

8、空间索引(SPATIAL)

二、索引的问题

1、哪些情况下适合建索引

2、哪些情况下不适合建索引

3、能用复合索引的要使用复合索引

4、null值也是可以走索引的,他被处理成最小值放在b+树的最左侧

5、使用短索引

6,排序的索引问题

7、MySQL索引失效的几种情况


前言:学习需静心,不可急躁求成!

innodb采用的是一种名为【b+树】的数据结构。

B-树有如下特点:

  1. 所有键值分布在整颗树中;
  2. 任何一个关键字出现且只出现在一个结点中;
  3. 搜索有可能在非叶子结点结束;
  4. 在关键字全集内做一次查找,性能逼近二分查找;

B+树】是【B-树】的变体,也是一种多路搜索树, 它与 B- 树的不同之处在于:

  1. 所有关键字存储在叶子节点
  2. 为所有叶子结点增加了一个双向指针

1、聚簇索引和非聚簇索引

我们在上边的例子中,【主键和数据】共存的索引被称之为【聚簇索引】,其他的,比如我们使用【姓名列+主键】建立的索引,可以称为【非聚簇索引】,或者【辅助索引】,或者【二级索引】,同时聚簇索引只有在innodb引擎中才存在,而在myIsam中是不存在的,如下图:

InnoDB使用的是【聚簇索引】,他会将【主键】组织到一棵B+树中,而【行数据】就储存在叶子节点上,若使用where id = 14这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。

若对Name列进行条件搜索,且name列已建立【索引】,则需要两个步骤:

  • 第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。
  • 第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。(重点在于通过其他键需要建立辅助索引)

tips:

  • 聚簇索引【默认使用主键】,如果表中没有定义主键,InnoDB 会选择一个【唯一且非空】的列代替。如果没有这样的列,InnoDB 会隐式定义一个主键【类似oracle中的RowId】rowid来作为聚簇索引的列。

  • 如果涉及到大数据量的排序、全表扫描、count之类的操作的话,还是MyIsam占优势些,因为索引所占空间小,这些操作是需要在内存中完成的。

小问题:主键为什么建议使用自增id?

  • 主键最好不要使用uuid,因为uuid的值太过离散,不适合排序且可能出现新增加记录的uuid,会插入在索引树中间的位置,出现页分裂,导致索引树调整复杂度变大,消耗更多的时间和资源。
  • 聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。如果主键不是自增id,它会不断地调整数据的物理地址、分页,当然也有其他一些措施来减少这些操作,但却无法彻底避免。但如果是自增的id,它只需要一 页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。

 2、普通索引 (常规索引)(normal)

例如创建user_name列的索引:

create index idx_user_name on user(user_name); 

创建索引是一个很费时间的操作。

其他创建索引的方法,如下:

(1)创建email列的索引,索引可以截取length长度,只使用这一列的前几个字符

create index idx_email on user(email(5));

有的列【数据量比较大】,使用前几个字符就能【很快标识】出来一行数据,那我们就可以使用这种方式建立索引,比如我们的邮箱,邮箱很多后缀是相同的我们完全可以忽略。

(2)使用修改表的方式添加索引 

alter table user add index idx_email (email);

(3)建表时时,同时创建索引

create table tbl_name(
    tid int,
    tname varchar(20),
    gender varchar(1),
    index [indexName] (fieldName(length))
)

3、唯一索引(UNIQUE )

对列的要求:索引列的值不能重复

创建表的同时,创建索引:

create table tbl_name(
    tid int,
    tname varchar(20),
    gender varchar(1),
    unique index unique_index_tname (tname)
)

独立的sql语句创建索引,我们的邮箱,用户名就应该创建唯一索引,姓名就应该是普通索引:

create unique index idx_email on user(email);

通过alter语句添加索引:

ALTER table mytable ADD UNIQUE [ux_indexName] (username(length))

唯一索引和主键的区别:

  • 唯一索引列允许空值,而主键列不允许为空值。
  • 主键列在创建时,已经默认为非空值 + 唯一索引了。
  • 主键可以被其他表引用为外键,而唯一索引不能。
  • 一个表最多只能创建一个主键,但可以创建多个唯一索引。
  • 主键更适合那些不容易更改的唯一标识,如自动递增列、身份证号等。

唯一约束和唯一索引的区别:

  • 唯一约束和唯一索引,都可以实现列数据的唯一,列值可以为null。
  • 创建唯一约束,会自动创建一个同名的唯一索引,该索引不能单独删除,删除约束会自动删除索引。唯一约束是通过唯一索引来实现数据唯一。
  • 创建一个唯一索引,这个索引就是独立的索引,可以单独删除。
  • 如果一个列上想有约束和索引,且两者可以单独的删除。可以先建唯一索引,再建同名的唯一约束。

4、多个二级索引的组合使用!

mysql在执行查询语句的时候一般只会使用【一个索引】,除非是使【用or连接的两个索引列】会产生索引合并。

我们针对某电商平台的检索功能做了优化,添加了三个索引,三个字段分别为【品牌】、【价格】、【销量】这三个的索引结构如下:

(1)品牌的索引结构:

image-20220517162932935

(2)价格的索引结构:

image-20220516145308003

(3)销量的索引结构:

image-20220516145354413

针对以上的索引我们进行如下的查询,分析检索过程:

  1. 我们要检索品牌为阿玛尼(Armani)的包包

    第一步:通过【品牌索引】检索出所有阿玛尼的商品id,回表查询,得到结果。

    结论:会使用一个索引。

  2. 我们要检索名称为阿玛尼(Armani),价格为26800,且销量在50以上的包包

    查询的步骤如下:

    第一步:通过【品牌索引】检索出所有阿玛尼的商品id,进行缓存。

    第二步:直接回表扫描,根据剩余条件检索结果。

    结论:只会使用第一个索引。

  3. 我们要检索名称为阿玛尼(Armani)或名称为LV的包包

    第一步:通过【品牌索引】检索出所有阿玛尼的商品id,得到结果。

    结论:像这样的【type =‘Armani’ or type = ‘LV’】,他相当于一个in关键字,会使用一个索引。

  4. 我们要检索名称为阿玛尼(Armani)或价格大于8000的包包

    第一步:通过【品牌索引】检索出所有阿玛尼的商品id,进行缓存。

    第二步:通过【价格索引】检索出价格在5万到7万之间的商品id,这是一个连接条件带有【or的查询】,所以需要和上一步的结果进行【并集】,得到结果。

    结论:这个过程叫【索引合并】当检索条件有or但是所有的条件都有索引时,索引不失效,可以走【两个索引】。

  5. 我们要检索名称为阿玛尼(Armani),价格大于8000,且【产地(该列无索引)】在北京的包包

    第一步:通过【品牌索引】检索出所有阿玛尼的商品id。

    第二步:直接回表扫描,根据剩余条件检索结果。

    结论:只会使用第一个索引。

  6. 我们要检索名称为阿玛尼(Armani)或价格大于8000,或产地(该列无索引)在北京的包包

    第一步:优化器发现【产地列】无索引,同时连接的逻辑是【or】没有办法利用【索引】优化,只能全表扫描,索引失效。

    结论发生全表扫描,索引失效,条件中有没建立索引的列,同时关联条件是or

5、复合索引(联合索引)!

当【查询语句】中包含【多个查询条件,且查询的顺序基本保持一致】时,我们推荐使用复合索引,索引的【组合使用】效率是低于【复合索引】的。

比如:我们经常按照A列、B列、C列进行查询时,通常的做法是建立一个由三个列共同组成的【复合索引】而不是对每一个列建立【普通索引】。

创建联合索引的方式如下:

alert table test add idx_a1_a2_a3 table (a1,a2,a3) 
-- 28.531s
create index idx_user_nick_name on ydl_user(user_name,nick_name,email(7));
  1. 我们要检索名称为阿玛尼(Armani),价格在1万到3万之间的包包

    第一步:通过【品牌索引】检索出所有阿玛尼的叶子节点。

    第二步:在【满足上一步条件的叶子节点中】查询价格在1万到3万之间的包包的列,查询出对应的id,回表查询列数据。

    结论:会使用复合索引的两个部分。

  2. 我们要检索名称为阿玛尼(Armani)或价格大于8000的包包

    第一步:优化器发现我们并没有一个【价格列】的单独的二级索引,此时要查询价格大于8000的包,必须进行全表扫描。

    结论:但凡查询的条件中没有【复合索引的第一部分】,索引直接【失效】,全表扫描。

  3. 我们要检索名称为阿玛尼(Armani),且价格大于8000,且【产地(该列无索引)】在北京的包包

    第一步:通过【品牌索引】检索出所有阿玛尼的叶子节点。

    第二步:在【满足上一步条件的叶子节点中】查询价格大于8000元的包包的叶子节点。

    第三步:因为【产地列】无索引,但是是【and】的关系,我们只需要将上一步得到的结果回表查询,在这个很小的范围内,检索产地是不是北京即可。

    结论:可以使用复合索引的两个部分。

  4. 我们要检索名称为阿玛尼(Armani)和LV之间,价格为在1万到3万的包包

    第一步:通过【品牌索引】检索出所有阿玛尼和LV的所有叶子节点。

    第二步:我们本想在第一步的结果中,快速定位价格的范围,但是发现一个问题,由于第一步不是等值查询,会导致后边的结果不连续,必须对【上一步的结果】全部遍历,才能拿到对应的结果。

    结论:只会使用复合索引的第一个部分,这个就引出了【复合索引中特别重要的一个概念】-【最左前缀原则】。

重点:最左前缀原则:

(1)最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 ,如果建立(a,b,c,d)顺序的联合索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

(2)= 和 in 可以乱序,比如a = 1 and b < 2 and c = 3 ,咱们建立的索引就可以是(a,c,b)或者(c,a,b)。

思考:为什么联合索引的性能会比索引的组合使用效率高。

6、全文索引(FULLTEXT)

做全文检索(不如百度的搜索功能)使用的索引,但是这种场景,我们有更好的替代品,如:ElacticSearch,所以实际使用不多,只当了解。

7、hash索引

hash索引是Memory存储引擎的默认方式,而且只有memory引擎支持hash索引,memory的数据是放在内存中的,一旦服务关闭,表中的数据就会丢失,我们可以使用如下的sql创建一张表:

CREATE TABLE `hash_user`  (
  `user_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `user_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户账号',
  ......
) ENGINE = Memory CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户信息表' ROW_FORMAT = Dynamic;

合理的使用memory引擎可以极大的提升性能,针对memory引擎的特点重启丢失),我们最好在其中存储一些公共的、常用的、不经常发生改变的数据,比如一些字典数据、配置数据等。同时,这些数据最好持久化在一些其他的地方,比如配置文件、其他的表,在程序启动的时候,主动的进行加载,我们可以使用如下sql,将一张表的数据加载到内存中:

insert into hash_user select * from ydl_user where user_id < 2000000;

在执行的过程种,可能有如下错误:

他告诉我,这个表使用的内存满了,放不下了,我们只需要调节下边两个参数,修改配置文件重启即可:

tmp_table_size = 4096M
max_heap_table_size = 4096M

基础工作完成,写几个sql语句尝试一下,我们发现真的一个字:快。

我们执行一下的sql

select * from hash_user where email = 'i.jnoyelrsg@rpnglcvh.museum'  -- 0.189s

创建一个hash索引

create index hash_idx_user_name using hash on hash_user(email);

再次查询

select * from hash_user where email = 'i.jnoyelrsg@rpnglcvh.museum'  -- 0.017s

也有不错的效果。

8、空间索引(SPATIAL)

MySQL在5.7之后的版本支持了空间索引,而且支持OpenGIS几何数据模型。这是在地理位置领域使用的一种索引,其他场景用的很少,所以不需要深入学习。

二、索引的问题

1、哪些情况下适合建索引

  • 频繁作为where条件语句查询的字段
  • 关联字段需要建立索引
  • 分组,排序字段可以建立索引
  • 统计字段可以建立索引,例如count(),max()等

小案例:有了索引之后的分组执行流程如下:

image-20220512173224645

直接使用索引信息,统计每个组的人数,直接返回。

2、哪些情况下不适合建索引

  • 频繁更新的字段不适合建立索引

  • where条件中用不到的字段不适合建立索引

  • 表数据可以确定比较少的不需要建索引

  • 数据重复且发布比较均匀的的字段不适合建索引(唯一性太差的字段不适合建立索引),例如性别,真假值

  • 参与列计算的列不适合建索引,索引会失效

3、能用复合索引的要使用复合索引

4、null值也是可以走索引的,他被处理成最小值放在b+树的最左侧

5、使用短索引

对字符串的列创建索引,如果可能,应该指定一个前缀长度。例如,如果有一个CHAR(255)的 列,如果在前10 个或20 个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

6,排序的索引问题

mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要,最好给这些列创建复合索引

7、MySQL索引失效的几种情况

为了确保索引能够有效地工作,应该定期分析查询计划(使用 EXPLAIN 关键字)

explain关键字icon-default.png?t=O83Ahttps://blog.csdn.net/m0_61160520/article/details/144391807?sharetype=blogdetail&sharerId=144391807&sharerefer=PC&sharesource=m0_61160520&sharefrom=mp_from_link

  • 如果条件中有or,即使其中有条件带索引也不会使用走索引,除非全部条件都有索引
  • 复合索引不满足最左原则就不能使用全部索引
  • like查询
  • 存在列计算
explain select * from student where age = (18-1)
  • 如果mysql估计使用全表扫描要比使用索引快,则不使用索引,比如结果的量很大
  • 隐式类型转换
-- 索引不失效
explain select * from student where age = '18'  
explain select * from ydl_user where login_date = '2008-05-31 17:20:54'
-- 索引失效 本来是字符串,你使用数字和他比较
explain select * from student where gander = 1

image-20220518183149811

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

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

相关文章

Oracle最佳实践-优化硬解析

前段时间参加oracle CAB&#xff0c;oracle高级服务部门做了一个数据库最佳实践的报告&#xff0c;其中就有一项就是解决未使用绑定变量但执行次数很多的SQL&#xff1b; 对于一个数据库来说如果不知道该如何优化&#xff0c;那么最简单最有效的优化就是减少硬解析&#xff0c;…

AI Agent:重塑业务流程自动化的未来力量(2/30)

《AI Agent&#xff1a;重塑业务流程自动化的未来力量》 摘要&#xff1a;整体思路是先介绍 AI Agent 的基本情况&#xff0c;再深入阐述其实现业务流程自动化的方法和在不同领域的应用&#xff0c;接着分析其价值和面临的挑战&#xff0c;最后得出结论&#xff0c;为读者全面…

哈默纳科Harmonic谐波减速机机器人精准高效动力传递的核心力量

在当今科技飞速发展的时代&#xff0c;机器人技术正以惊人的速度改变着我们的生产与生活方式。而在机器人的精密机械结构中&#xff0c;哈默纳科 Harmonic 谐波减速机扮演着不可或缺的角色&#xff0c;成为机器人精准高效动力传递的关键所在。 1.高精度与灵活性&#xff1a;哈默…

【开源项目】经典开源项目数字孪生体育馆—开源工程及源码

飞渡科技数字孪生体育馆管理平台&#xff0c;融合物联网IOT、BIM数据模型、三维GIS等技术&#xff0c;实现体育馆的全方位监控和实时全局掌握&#xff0c;同时&#xff0c;通过集成设备设施管理、人员管理等子系统&#xff0c;减少信息孤岛&#xff0c;让场馆“可视、可控、可管…

长短期记忆神经网络(LSTM)介绍

1、应用现状 长短期记忆神经网络&#xff08;LSTM&#xff09;是一种特殊的循环神经网络(RNN)。原始的RNN在训练中&#xff0c;随着训练时间的加长以及网络层数的增多&#xff0c;很容易出现梯度爆炸或者梯度消失的问题&#xff0c;导致无法处理较长序列数据&#xff0c;从而无…

SQL server学习03-创建和管理数据表

目录 一&#xff0c;SQL server的数据类型 1&#xff0c;基本数据类型 2&#xff0c;自定义数据类型 二&#xff0c;使用T-SQL创建表 1&#xff0c;数据完整性的分类 2&#xff0c;约束的类型 3&#xff0c;创建表时创建约束 4&#xff0c;任务 5&#xff0c;由任务编写…

正则表达式——参考视频B站《奇乐编程学院》

智能指针 一、背景&#x1f388;1.1. 模式匹配&#x1f388;1.2. 文本替换&#x1f388;1.3. 数据验证&#x1f388;1.4. 信息提取&#x1f388;1.5. 拆分字符串&#x1f388;1.6. 高级搜索功能 二、原料2.1 参考视频2.2 验证网址 三、用法3.1 限定符3.1.1 ?3.1.2 *3.1.3 3.1.…

Elasticsearch 集群部署

Elasticsearch 是一个分布式的搜索和分析引擎&#xff0c;广泛应用于日志分析、全文搜索、实时数据分析等场景。它以其高性能、高可用性和易用性而著称。本文档将引导您完成一个基本的 Elasticsearch 集群配置&#xff0c;包括节点间的通信、客户端访问、安全设置等关键步骤。我…

#思科模拟器通过服务配置保障无线网络安全Radius

演示拓扑图&#xff1a; 搭建拓扑时要注意&#xff1a; 只能连接它的Ethernet接口&#xff0c;不然会不通 MAC地址绑定 要求 &#xff1a;通过配置MAC地址过滤禁止非内部员工连接WiFi 打开无线路由器GUI界面&#xff0c;点开下图页面&#xff0c;配置路由器无线网络MAC地址过…

webstorm开发uniapp(从安装到项目运行)

1、下载uniapp插件 下载连接&#xff1a;Uniapp Tool - IntelliJ IDEs Plugin | Marketplace &#xff08;结合自己的webstorm版本下载&#xff0c;不然解析不了&#xff09; 将下载到的zip文件防在webstorm安装路径下&#xff0c;本文的地址为&#xff1a; 2、安装uniapp插…

mHand Pro动捕数据手套在人形机器人领域的具体运用

mHandPro是一款高精度的动作捕捉数据手套&#xff0c;可应用于动作捕捉与VR交互等领域&#xff0c;配套”mHand Studio“引擎&#xff0c;可实时捕捉真人手部位姿及运动轨迹数据&#xff0c;将数据导出还可以用于人形机器人的训练加速高精度机器人操作技能的培训进程。 高精度动…

CNCF云原生生态版图-分类指南(三)- 运行时

CNCF云原生生态版图-分类指南&#xff08;三&#xff09;- 运行时 CNCF云原生生态版图-分类指南三、运行时&#xff08;Runtime&#xff09;&#xff08;一&#xff09;云原生存储&#xff08;Cloud Native Storage&#xff09;1. 是什么&#xff1f;2. 解决什么问题&#xff1…

算法论文/半监督1——2024最新半监督目标检测综述(CNN和Transformer)全文1.5W字

Semi-Supervised Object Detection: A Survey on Progress from CNN to Transformer 摘要 半监督学习的惊人进步促使研究人员探索其在计算机视觉领域内目标检测任务中的潜力。半监督对象检测 &#xff08;SSOD&#xff09; 利用小型标记数据集和较大的未标记数据集的组合。这…

LLMC:大语言模型压缩工具的开发实践

关注&#xff1a;青稞AI&#xff0c;学习最新AI技术 青稞Talk主页&#xff1a;qingkelab.github.io/talks 大模型的进步&#xff0c;正推动我们向通用人工智能迈进&#xff0c;然而庞大的计算和显存需求限制了其广泛应用。模型量化作为一种压缩技术&#xff0c;虽然可以用来加速…

【Linux】常用Linux命令大全(持续更新)

前言 汇总常用linux命令及用法&#xff0c;方便大家在日常工作中操作linux的便捷性 一、top命令 top 是一个在 Linux 系统上常用的实时系统监控工具。它提供了一个动态的、交互式的实时视图&#xff0c;显示系统的整体性能信息以及正在运行的进程的相关信息    在键入top命令…

VLC还是SmartPlayer?Windows平台RTSP播放器低延迟探讨

技术背景 好多开发者在用过大牛直播SDK的RTSP播放器后&#xff0c;都希望我们也分享下&#xff0c;如何在Windows平台实现低延迟的RTSP播放&#xff1f;低延迟的RTSP播放器&#xff0c;说起来容易做起来难&#xff0c;下面&#xff0c;我们从以下维度做个探讨&#xff1a; 播…

28. Three.js案例-创建圆角矩形并进行拉伸

28. Three.js案例-创建圆角矩形并进行拉伸 实现效果 知识点 WebGLRenderer (WebGL渲染器) WebGLRenderer 是 Three.js 中用于渲染 3D 场景的主要渲染器。 构造器 WebGLRenderer( parameters : Object ) 参数类型描述parametersObject渲染器的配置参数&#xff0c;可选。 …

启明智显ZX7981PC:5G时代的新选择,全屋网络无缝覆盖

在这个飞速发展的5G时代&#xff0c;每一个细微的科技进步都在推动着我们的生活向更加智能、便捷的方向发展。近日&#xff0c;启明智显再次引领科技潮流&#xff0c;正式发布其最新的5G CPE产品——ZX7981PC。作为继7981PG与7981PM之后的又一次迭代升级&#xff0c;ZX7981PC凭…

Qt控件的盒子模型,了解边距边线和内容区

这篇专门讲讲一个控件在绘制时的视觉样式。我们平常在对控件设置样式时&#xff0c;需要设置控件的一些外边距&#xff0c;内边距&#xff0c;边线&#xff0c;还有文字内容&#xff0c;贴上图片等。那么对于一个控件&#xff0c;到底怎么实现这些设置的呢&#xff1f; 先看下面…

docker简单私有仓库的创建

1&#xff1a;下载Registry镜像 导入镜像到本地中 [rootlocalhost ~]# docker load -i registry.tag.gz 进行检查 2&#xff1a;开启Registry registry开启的端口号为5000 [rootlocalhost ~]# docker run -d -p 5000:5000 --restartalways registry [rootlocalhost ~]# dock…