索引(一)

(一)索引定义。在我们添加完索引之后,mysql一般通过btree算法生成一个索引文件,在查询数据库时,找到索引文件进行遍历(折半查找大幅查询效率),找到相应的键从而获取数据。

(二)索引分类。

   1、普通索引。最基本的索引,没有任何限制。

alter table table_name      add index    index_name(firstname,lastname,age) ; 

   2、唯一索引。与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值(注意和主键不同)。如果是组合索引,则列值的组合必须唯一。

   3、主键索引。它是一种特殊的唯一索引,不允许有空值。

alter table table_name      add primary key(主键列名称) ; 

   4、全文索引。针对较大的数据,生成全文索引很耗时好空间。

    (1)创建表的同时创建全文索引。create table。

create table article (
id int auto_increment not null primary key,
title varchar(200),
body text,
fulltext(title, body)
) type=myisam;

    (2)alter table 方式。(可以省掉index关键字)

alter table  student add fulltext              address_fulltext(address);

alter table  student add fulltext index    address_fulltext(address);

    (3)直接创建。

create fulltext index addressinfo_fulltext on student(address,information);

create fulltext index 全文索引名称   on  表名称(列名称列表);

注意此处的index关键字不能省略。

       (4)删除索引。

drop index 全文索引名称   on  数据库名.表名;

alter table 数据库名.表名   drop index   全文索引名称;

   5、组合索引。为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“原则。

   6、哈希索引。mysql中只有在memory引擎显示支持哈希索引。

   7、B树索引。B-tree索引能够加快访问数据的速度,因为存储引擎不再需要经行全表扫描来获取需要的数据,取而代之的是从根节点开始搜索。根节点的槽中存放了指向子节点的指针,存储引擎根据这些指针向下查找。通常比较节点页的值和要查找的值可以找到合适的指针进入下层子节点。

如上图,是一颗B-tree,关于B-tree的定义可以参见B-tree,这里只说一些重点,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块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并不真实存在于数据表中。

B-tree的查找过程。如图所示,如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计,通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时内存中做二分查找找到29,结束查询,总计三次IO。真实的情况是,3层的B-tree可以表示上百万的数据,如果上百万的数据查找只需要三次IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共需要百万次的IO,显然成本非常非常高。
   (1)通过上面的分析,我们知道IO次数取决于b+数的高度h,假设当前数据表的数据为N,每个磁盘块的数据项的数量是m,则有h=㏒(m+1)N,当数据量N一定的情况下,m越大,h越小;而m = 磁盘块的大小 / 数据项的大小,磁盘块的大小也就是一个数据页的大小,是固定的,如果数据项占的空间越小,数据项的数量越多,树的高度越低。这就是为什么每个数据项,即索引字段要尽量的小,比如int占4字节,要比bigint8字节少一半。这也是为什么B-tree要求把真实的数据放到叶子节点而不是内层节点,一旦放到内层节点,磁盘块的数据项会大幅度下降,导致树增高。当数据项等于1时将会退化成线性表。
   (2)当B-tree的数据项是复合的数据结构,比如(name,age,sex)的时候,b+数是按照从左到右的顺序来建立搜索树的,比如当(张三,20,F)这样的数据来检索的时候,B-tree会优先比较name来确定下一步的所搜方向,如果name相同再依次比较age和sex,最后得到检索的数据;但当(20,F)这样的没有name的数据来的时候,B-tree就不知道下一步该查哪个节点,因为建立搜索树的时候name就是第一个比较因子,必须要先根据name来搜索才能知道下一步去哪里查询。比如当(张三,F)这样的数据来检索时,B-tree可以用name来指定搜索方向,但下一个字段age的缺失,所以只能把名字等于张三的数据都找到,然后再匹配性别是F的数据了, 这个是非常重要的性质,即索引的最左匹配特性。
B-tree索引适用于全值匹配、匹配最左前缀、匹配列前缀、匹配范围值。注意:B-tree的高度一般都在2-4层,这也就是说查找某一键值的行记录最多只要2到4次IO,花费0.02-0.04秒左右。

(三)索引代价。

   1、创建索引会产生索引文件的,占用磁盘空间。

   2、对于DML操作,比如DELETE、UPDATE以及INSERT操作,索引会降低它们的速度。这是因为MySQL不仅要把改动数据写入数据文件,而且它还要把这些改动写入索引文件。

原文地址:https://www.cnblogs.com/igoodful/p/9154361.html