跟着项目学sql(五) 索引(上)

版权声明:本文为博主原创文章,未经博主允许不得转载。博客地址: https://blog.csdn.net/m0_37057454/article/details/82758006

开头还是百度百科中的【索引】相关术语

在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。

索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。数据库使用索引以找到特定值,然后顺指针找到包含该值的行。这样可以使对应于表的SQL语句执行得更快,可快速访问数据库表中的特定信息。

当表中有大量记录时,若要对表进行查询,第一种搜索信息方式是全表搜索,是将所有记录一一取出,和查询条件进行一一对比,然后返回满足条件的记录,这样做会消耗大量数据库系统时间,并造成大量磁盘I/O操作;第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录。

通过阅读上面一大段术语,我们可以得出三点信息:

1)、对表进行查询有两种方式:全表搜索索引

2)、当表中有大量记录时,用全表扫描会消耗大量数据库系统时间和磁盘I/O,因此要使用索引。

3)、索引是数据库表中一列或多列的值进行排序的一种存储结构,至少包含索引值ROWID,数据库使用索引以找到特定值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录。

新闻表(News)

序号 名称 数据类型 长度 小数位 允许空值 主键 默认值 说明
1 id varchar(36) 36 0 N Y    
2 title varchar(200) 200 0 N      
3 keywords varchar(200) 200 0 Y      
4 author varchar(45) 45 0 N     新闻来源
5 thumb varchar(200) 200 0 Y     缩略图
6 content text 65535 0 N     新闻内容
7 user_id varchar(45) 45 0 Y     创建人id
8 username varchar(45) 45 0 Y     创建人
9 create_time datetime 23 0 Y   CURRENT_TIMESTAMP  
10 edit_time datetime 23 0 Y      
11 state tinyint(3) UNSIGNED 3 0 Y   0  

1、全表搜索索引【MySql InnoDB下】

新闻表中的id上有主键索引,其他字段没有索引,来看我们的新闻发布系统中最关键的功能:

select 字段 from news where id=***

因此,大部分情况下,在关系型数据库中,我们总能在关键功能中用到索引,不管有意无意,无关数据量多少。

在用户表中有5条测试数据,我们试图用它来对比全表搜索和索引,结果发现时间全是0,并没有看出任何区别:

为此,我们在新闻表中插入2W条测试数据,格式如下

分别查找id为【空字符串】的新闻 、title为【空字符串】的新闻,对比结果如下:

我用的设备硬盘陈旧,所以对比结果非常明显,我们把正在运行的IDE、QQ、360、浏览器等等全部退出,来看下结果:

根据以上信息得出三点结论

1)数据量小的情况下,全表扫描和索引差距不大。

2)提升机器性能,优化了查询,机器配置越高,查询速度越快。

3)在相同的机器配置下,索引明显优于全表搜索。

现在,我的需求就是在数据库执行查询的同时,还可以安心的写代码、看视频、下载、聊qq。

从数据库的角度来看,确实是我看视频等操作影响了查询效率,但是从我的角度来看,数据库查询还影响我看视频了呢。全表扫描速度过慢,占据大量磁盘IO,耗时很长,这导致我在看视频的时候总是特别卡。

我第一个想到的解决办法,给我的机器换个好点儿的硬盘,这样不光数据库性能得到提升,估计这边跑着数据库,那边放着视频玩儿吃鸡都没问题了。但现实是,我没有资金,所以并不能奢望给机器换啥配置

第二个想到的办法就是把数据库踢掉,放到别的电脑上,爱搁哪搁哪儿,反正不能影响我看视频。用专门的数据库服务器,固态盘。但现实是,我连给自己换机器的资金都没有。

万幸的是,在使用索引的情况下,数据库查询性能还是可以接受的,耗时少,意味着我在看视频的时候受到的影响也比较小。

2、索引的创建

为新闻表中的title字段添加索引,如下图,现在只有一个主键索引,选中title字段,点击create index按钮。

 弹出创建索引对话框,索引类型下拉框里有四个选项,分别是Non-Unique(非唯一索引)、Unique(唯一索引)、FullText(全文索引)、Spatial(空间索引),其中Spatial(空间索引)针对GIS空间数据字段类型,比如POINT、POLYGON等,笔者并没有这方面的经验,不做讨论。

 

那现在有三个选择:Non-Unique(普通索引)、Unique(唯一索引)、FullText(全文索引),分别为Id列加上这三种索引,再加上主键索引,现在id列就拥有四个索引了,如下图:

我们可以根据表格中的内容给索引分一下类:

1)根据Key的不同可以分为主键(聚集)索引和非聚集索引,只能有一个主键,所以只能有一个主键(聚集)索引。

见上图,mysql中【PRIMARY】是主键索引的御用名称,并不能为其他字段创建name为PRIMARY的索引,即并不能手动创建主键索引,而是在给字段添加主键约束时会自动创建主键索引。

2)根据Type的不同可以分为BTREE索引和FULLTEXT索引。主键(聚集)索引、唯一索引和普通索引都是BTREE索引。

3)根据Unique的不同可以分为唯一索引和普通(非唯一)索引。主键索引是唯一索引,全文索引不是唯一索引。

--------------------------------------------------------------------------------------------------------------------------------------

堆组织表(heap table):

数据插入时时存储位置是随机的,主要是数据库内部块的空闲情况决定,获取数据是按照命中率计算,全表扫表时不见得先插入的数据先查到。

索引组织表(iot):

数据存储是把表按照索引的方式存储的,数据是有序的,数据的位置是预先定好的,与插入的顺序没有关系。

-----------------------------------------------------------------------------------------------------------------------------------------

InnoDB是聚集索引组织表,它的聚集索引选择规则如下:

1)首先选择显式定义的主键索引做为聚集索引;

2)如果没有主键被定义,那么该表的第一个唯一非空索引被作为聚集索引。

3)如果没有唯一非空索引,那么就采用InnoDB引擎内置的ROWID作为聚集索引。

因此,在Innodb下,主键=主键约束=主键索引=聚集索引。

BTREE索引

Innodb的BTREE索引是基于B+tree,分为聚集索引和非聚集索引。

聚集索引:

聚集索引就是按照每张表的主键构造一颗B+树,同时叶子结点存放的即为整张表的行纪录数据(聚集索引的叶子结点也称为数据页)。聚集索引的这个特性也决定了索引组织表中数据也是索引的一部分,和B+树数据结构一样,每个数据页之间都通过一个双向链表来进行链接。

聚集索引表记录的排列顺序和索引的排列顺序一致,所以查询效率快,只要找到第一个索引值记录,其余就连续性的记录在物理也一样连续存放。聚集索引对应的缺点就是修改慢,因为为了保证表中记录的物理和索引顺序一致,在记录插入的时候,会对数据页重新排序。

非聚集索引:

非聚集索也采用了B+树结构,制定了表中记录的逻辑顺序,不同的是,非聚集索引的叶子层并不和实际数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针方式。

如果表是堆集(没有聚集索引),行定位器就是指向行的指针。该指针用文件标识符 (ID)、页码和页上的行数生成。整个指针称为行 ID。如果表有聚集索引,或者索引在索引视图上,则行定位器就是行的聚集索引键。

而在Innodb中,必有聚集索引,因此行定位器就是行的聚集索引键,非聚集索引层次多,不会造成数据重排。

Innodb中的每张表都会有一个聚集索引,而聚集索引又是以物理磁盘顺序来存储的,在使用自增主键时会把数据自动向后插入,避免了插入过程中的聚集索引排序问题。聚集索引的排序,必然会带来大范围的数据的物理移动,这里面带来的磁盘IO性能损耗是非常大的。

这也是在无特殊需求下Innodb建议使用与业务无关的自增ID作为主键的原因之一。

我们的News表采用GUID做主键,GUID在数据迁移,系统数据合并等情况下自有它的优势。但现在,我们发现在Innodb下使用GUID做主键,就等同于用GUID做聚集索引,而GUID本身是乱序的,会对索引的维护带来性能上的损耗,数据量越大越明显。

暂时能想到的是有一个comb主键生成有序GUID的方案,有时间的话可以看下是否可行。并没有很强烈的意愿去搞它,总觉得搞来搞去不如整形自增ID,因为自增ID可以控制自增变量的,借此就可以精心设计出一个好的方案来应对整形自增ID的不足。

插一道面试题——主键索引和唯一索引的区别:

mysql Innodb下,主键约束=主键索引=聚集索引,唯一约束=唯一索引。

主键索引是聚集唯一索引,其他的唯一索引是非聚集唯一索引。这道题出现的主要原因就是mysql中唯一约束=唯一索引。

 

猜你喜欢

转载自blog.csdn.net/m0_37057454/article/details/82758006