聚集索引,非聚集索引,覆盖索引

https://blog.csdn.net/itguangit/article/details/82145322

https://www.cnblogs.com/happyflyingpig/p/7662881.html

               一个没有主键的表,在数据无序的存储在磁盘上;

            一个表加了主键,这个表在磁盘上的存储结构就转变为树状结构,即平衡树结构,同时也是索引;

           此时整个表变为一个索引,即 聚集索引

 

聚集索引:

               也称为 主键索引

               表中的数据按照索引的顺序存储,即索引存储着数据, 检索效率比非聚集索引高,但是对数据更新影响大,因为修改数据会改变平衡树各个节点的内容;破坏树得到结构;

               聚集索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的即为整张表的记录数据。

               聚集索引的叶子节点称为数据页,聚集索引的这个特性决定了索引组织表中的数据也是索引的一部分。

 

     

非聚集索引

               也称为 辅助索引(二级索引)

               和聚集索引一样,采用平衡树作为索引的数据结构。索引树结构中各节点的值来自于表中的索引字段, 假如给user表的name字段加上索引 , 那么索引就是由name字段中的值构成,在数据改变时, DBMS需要一直维护索引结构的正确性。如果给表中多个字段加上索引 , 那么就会出现多个独立的索引结构,每个索引(非聚集索引)互相之间不存在关联。

               非主键索引,叶子节点=键值+书签。Innodb存储引擎的书签就是相应行数据的主键索引值

               每次给字段建一个新索引, 字段中的数据就会被复制一份出来, 用于生成索引。 因此, 给表添加索引,会增加表的体积, 占用磁盘存储空间。

 

//建立索引

create index index_birthday on user_info(birthday);

//查询生日在1991年11月1日出生用户的用户名

select user_name from user_info where birthday = '1991-11-1'

         SQL语句的执行过程如下:

               先通过非聚集索引 index_birthday 查找 birthday 为 1991-11-1 的所有记录的主键ID值。

               然后,通过得到的主键ID值执行聚集索引查找,找到主键ID值对的真实数据(数据行)存储的位置。

               最后,从得到的真实数据中取得 user_name 字段的值返回。

      

非聚集索引和聚集索引:

               区别在于, 通过聚集索引可以查到需要查找的数据, 而通过非聚集索引可以查到记录对应的主键值 , 再使用主键的值通过聚集索引查找到需要的数据,如下图

    

覆盖索引:

               就是平时所说的复合索引或者多字段索引查询。 文章上面的内容已经指出, 当为字段建立索引以后, 字段中的内容会被同步到索引之中, 如果为一个索引指定两个字段, 那么这个两个字段的内容都会被同步至索引之中。

               就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。

               索引是高效找到行的一个方法,当能通过检索索引就可以读取想要的数据,那就不需要再到数据表中读取行了。如果一个索引包含了(或覆盖了)满足查询语句中字段与条件的数据就叫 做覆盖索引。

               是非聚集组合索引的一种形式,它包括在查询里的Select、Join和Where子句用到的所有列(即建立索引的字段正好是覆盖查询语句[select子句]与查询条件[Where子句]中所涉及的字段,也即,索引包含了查询正在查找的所有数据)

               把 birthday 字段上的索引改成双字段的覆盖索引     

create index index_birthday_and_user_name on user_info(birthday, user_name);

              SQL语句的执行过程就会变为:

             通过非聚集索引index_birthday_and_user_name查找birthday等于1991-11-1的叶节点的内容,然而, 叶节点中除了有user_name表主键ID的值以外, user_name字段的值也在里面, 因此不需要通过主键ID值的查找数据行的真实所在, 直接取得叶节点中user_name的值返回即可。

原文地址:https://www.cnblogs.com/Jomini/p/13213846.html