数据库索引

一、索引简介

1.索引是什么?

MySQL官对索引的定义为:索引(Index)是帮助MySQL搞笑获取数据的数据结构。即得到索引的本质:索引是数据结构。

1)你可以理解为“排好序的快速查找数据结构”。

详解(重要):

在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。下图就是一种可能的索引方式示例:

             数据库索引

               左边是数据表,一共有两列七条记录,最左边的时数据鸡柳的物理地址。

为了加快 Col2 的查找,可以维护一个右边所示的二叉查找树,每个姐弟啊分别包含索引键值和一个指向对应数据记录地址的指针,这样就可以运用二叉查找在一定的复杂度内获取到相应数据,从而快速的检索出符合条件的记录。

我们平时所说的索引,如果没有特别指明,都是指 B 树(多路搜索树,并不一定是二叉树)结构组织的索引。其中聚集索引,次要索引,覆盖索引,复合索引,前缀索引,唯一索引默认都是使用 B+树索引,统称索引。当然,除了B+树这种类型的索引之外,还有哈希索引(hash index)等。

2.索引的优势和劣势

优势:

  • 类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本。
  • 通过索引列队数据进行排序,降低数据排序的成本,降低了CPU的消耗。

劣势:

  • 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的。
  • 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对标进行insert、update和delete。因为更新表时,MySQl不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新索带来的键值变化后的索引信息。
  • 索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询。

3.MySQL的索引分类

1)单值索引

即一个索引值包含单个列,一个表可以有多个单列索引

创建方法:

a. 建表的时候一起创建

  CREATE TABLE mytable ( name VARCHAR(32) , INDEX index_mytable_name (name) );

b. 建表后,直接创建索引

  CREATE INDEX index_mytable_name ON mytable(name);

c. 修改表结构

  ALTER TABLE mytable ADD INDEX index_mytable_name (name);

注:如果是字符串字段,还可以指定索引的长度,在列命令后面加上索引长度就可以了(例如:name(11))

2)唯一索引

索引列的值必须是唯一的,但允许有空值。(银行卡号)

创建方法:

a. 建表的时候一起创建

  CREATE TABLE mytable ( `name` VARCHAR(32) , UNIQUE index_unique_mytable_name              (`name`) );

b. 建表后,直接创建索引

  CREATE UNIQUE INDEX index_mytable_name ON mytable(name);

c. 修改表结构

  ALTER TABLE mytable ADD UNIQUE INDEX index_mytable_name (name);

注:如果是字符串字段,还可以指定索引的长度,在列命令后面加上索引长度就可以了(例如:name(11))

3)复合索引

即一个索引包含多个列。

创建方法:

a. 建表的时候一起创建

  CREATE TABLE mytable ( `id` int(11) , `name` VARCHAR(32) , INDEX index_mytable_id_name            (`id`,`name`) );

b. 建表后,直接创建索引

  CREATE INDEX index_mytable_id_name ON mytable(id,name);

c. 修改表结构

  ALTER TABLE mytable ADD INDEX index_mytable_id_name (id,name);

4)主键索引

是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引。

创建方法:

a. 建表的时候一起创建

  CREATE TABLE mytable ( `id` int(11) NOT NULL AUTO_INCREMENT , `name` VARCHAR(32)   , PRIMARY KEY (`id`) );

b. 修改表结构

  ALTER TABLE test.t1 ADD CONSTRAINT t1_pk PRIMARY KEY (id);

注:如果是字符串字段,还可以指定索引的长度,在列命令后面加上索引长度就可以了(例如:name(11))

5)全文索引

主要用来查找文本中的关键字,而不是直接与索引中的值相比较。

fulltext索引跟其它索引大不相同,它更像是一个搜索引擎,而不是简单的where语句的参数匹配。

fulltext索引配合match against操作使用,而不是一般的where语句加like。

它可以在create table,alter table ,create index使用,不过目前只有char、varchar,text 列上可以创建全文索引。

创建方法:

a. 建表的时候一起创建

  CREATE TABLE `article` ( `id` int(11) NOT NULL AUTO_INCREMENT ,`title` char(250) NOT NULL   , `contents` text NULL , `create_at` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), FULLTEXT   (contents) );

b. 建表后,直接创建索引

  CREATE FULLTEXT INDEX index_article_contents ON article(contents);

c. 修改表结构

  ALTER TABLE article ADD FULLTEXT INDEX index_article_contents (contents);

6)基本语法

创建:

① create [unique] index indexName on mytable(columnName(length));

② alert mytable add [unique] index [indexName] on (columnName(length));

删除:

drop index [indexName] on mytable;

查看:

show index from table_name\G

4.MySQL索引结构

1)B+ 树

数据库索引

 【初始化介绍】

一颗 B+ 树,浅蓝的的快我们成为磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块1包含数据项17和35,包含指针P1,P2,P3。

P1表示洗浴17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。

真实的数据存在于叶子节点即3、5、9、10、13、15、28、29、36、60、75、79、90、99。

非叶子节点不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。

【查找过程】

如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次I口, 在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,内存时间因为非常短(相比磁盘的I0)可以忽略不计,通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次I0,29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次I0,同时内存中做二分查找找到29,结束查询,总计三次I0。

真实的情况是,3层的b+树可以表示上百万的数据,如果上百万的数据查找只需要三次I0,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次I0,那么总共需要百万次的I0,显然成本非常非常高。

5.哪些情况需要创建索引?
1)主键自动建立唯一索引。

2)频繁作为查询条件的字段应该创建索引。

3)查询中与其他表关联的字段,外键关系建立索引。

4)单键/组合索引的选择问题?(在高并发下倾向创建组合索引)。

5)查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度。

6)查询中统计或者分组字段。

6.哪些情况不需要创建索引?

1)表记录太少

2)经常增删改的表,why:提高了查询速度,同时却会降低更新表的速度,如对表进行insert、update、delete,因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

3)where 条件里用不到的字段不创建索引。

4)数据重复且分布均匀的表字段,因此应该只为最经常查询和最经常排序的数据列建立索引。注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。