博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
超易懂mysql索引
阅读量:3963 次
发布时间:2019-05-24

本文共 2567 字,大约阅读时间需要 8 分钟。

文章目录

例子

#创建一个名为user的表,其包括id,name,age,sex等字段信息。此外,id为主键聚簇索引,idx_name为非聚簇索引。CREATE TABLE `user` (  `id` varchar(10) NOT NULL DEFAULT '',  `name` varchar(10) DEFAULT NULL,  `age` int(11) DEFAULT NULL,  `sex` varchar(10) DEFAULT NULL,  PRIMARY KEY (`id`),  KEY `idx_name` (`name`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8; #我们将其设置10条数据,便于下面的索引的理解。INSERT INTO `user` VALUES ('1', 'andy', '20', '女');INSERT INTO `user` VALUES ('10', 'baby', '12', '女');INSERT INTO `user` VALUES ('2', 'kat', '12', '女');INSERT INTO `user` VALUES ('3', 'lili', '20', '男');INSERT INTO `user` VALUES ('4', 'lucy', '22', '女');INSERT INTO `user` VALUES ('5', 'bill', '20', '男');INSERT INTO `user` VALUES ('6', 'zoe', '20', '男');INSERT INTO `user` VALUES ('7', 'hay', '20', '女');INSERT INTO `user` VALUES ('8', 'tony', '20', '男');INSERT INTO `user` VALUES ('9', 'rose', '21', '男');

聚簇索引(主键索引)

在这里插入图片描述

他包含两个特点:

1.使用记录主键值的大小来进行记录和页的排序。

页内的记录是按照主键的大小顺序排成一个单项链表。
各个存放用户记录的页也是根据页中用户记录的主键大小顺序排成一个双向链表。
2.叶子节点存储的是完整的用户记录。

注:聚簇索引不需要我们显示的创建,他是由InnoDB存储引擎自动为我们创建的。如果没有主键,其也会默认创建一个。

非聚簇索引(二级索引)

上面的聚簇索引只能在搜索条件是主键时才能发挥作用,因为聚簇索引可以根据主键进行排序的。如果搜索条件是name,在刚才的聚簇索引上,我们可能遍历,挨个找到符合条件的记录,但是,这样真的是太蠢了,MySQL不会这样做的。

如果我们想让搜索条件是name的时候,也能使用索引,那可以多创建一个基于name的二叉树。如下图。
在这里插入图片描述
他与聚簇索引的不同:
1.叶子节点内部使用name字段排序,叶子节点之间也是使用name字段排序。
2.叶子节点不再是完整的数据记录,而是name和主键值。

为什么不再是完整信息?

MySQL只让聚簇索引的叶子节点存放完整的记录信息,因为如果有好几个非聚簇索引,他们的叶子节点也存放完整的记录绩效,那就不浪费空间啦。

如果我搜索条件是基于name,需要查询所有字段的信息,那查询过程是啥?

1.根据查询条件,采用name的非聚簇索引,先定位到该非聚簇索引某些记录行。
2.根据记录行找到相应的id,再根据id到聚簇索引中找到相关记录。这个过程叫做回表。

联合索引

如果name和age组成一个联合索引,那么先按name排序,如果name一样,就按age排序。

一些原则

1.最左前缀原则。一个联合索引(a,b,c),如果有一个查询条件有a,有b,那么他则走索引,如果有一个查询条件没有a,那么他则不走索引。

2.使用唯一索引。具有多个重复值的列,其索引效果最差。例如,存放姓名的列具有不同值,很容易区分每行。而用来记录性别的列,只含有“男”,“女”,不管搜索哪个值,都会得出大约一半的行,这样的索引对性能的提升不够高。

3.不要过度索引。每个额外的索引都要占用额外的磁盘空间,并降低写操作的性能。在修改表的内容时,索引必须进行更新,有时可能需要重构,因此,索引越多,所花的时间越长。

4、索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’);

5.一定要设置一个主键。前面聚簇索引说到如果不指定主键,InnoDB会自动为其指定主键,这个我们是看不见的。反正都要生成一个主键的,还不如我们设置,以后在某些搜索条件时还能用到主键的聚簇索引。

6.主键推荐用自增id,而不是uuid。上面的聚簇索引说到每页数据都是排序的,并且页之间也是排序的,如果是uuid,那么其肯定是随机的,其可能从中间插入,导致页的分裂,产生很多表碎片。如果是自增的,那么其有从小到大自增的,有顺序,那么在插入的时候就添加到当前索引的后续位置。当一页写满,就会自动开辟一个新的页。

注:如果自增id用完了,那将字段类型改为bigint,就算每秒1万条数据,跑100年,也没达到bigint的最大值。

万年面试题(为什么索引用B+树)

1、 B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。

2、由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。

转载地址:http://nqezi.baihongyu.com/

你可能感兴趣的文章
spring beans beanfactory applicationcontext
查看>>
使用ORM工具进行数据访问
查看>>
使用ORM工具进行数据访问
查看>>
编译与部署Eclipse+Tomcat+MySQL+Liferay4.1.2
查看>>
POJ3728,The merchant(倍增LCA+分治)
查看>>
2019 ICPC Malaysia National,E. Optimal Slots(01背包变形)
查看>>
洛谷P1638 逛画展(双向队列)
查看>>
POJ2892,Tunnel Warfare(线段树维护连续区间)
查看>>
POJ3468,A Simple Problem with Integers(线段树-区间查询-区间更新)
查看>>
杭电ACM——6463(思维)
查看>>
杭电ACM——2069,Coin Change(DP)
查看>>
杭电ACM——2110,Crisis of HDU(母函数)
查看>>
杭电AM——2152,Fruit(母函数)
查看>>
杭电ACM——2566,统计硬币(DP)
查看>>
堆栈(数据结构)
查看>>
队列(数据结构)
查看>>
Mule ESB-Content-Based Routing Tutorial(1)
查看>>
Mule ESB-Content-Based Routing Tutorial(2)
查看>>
Mule ESB-Content-Based Routing Tutorial(3)
查看>>
年末项目经验总结
查看>>