MySQL官方对索引的定义:索引(Index)是帮助MySQL高效获取数据的数据结构,这些数据结构以某种方式引用(指向)数据。索引的本质是:数据结构。可以简单理解为“排好序的快速查找数据结构”
一个非常恰当的比喻就是书的目录页与书的正文内容之间的关系,为了方便查找书中的内容,通过对内容建立索引形成目录。因此,首先你要明白的一点就是,索引它也是一个文件,它是要占据物理空间的。
比如对于MyISAM存储引擎来说:
.frm 后缀的文件存储的是表结构。
.myd 后缀的文件存储的是表数据。
.myi 后缀的文件存储的就是索引文件。
对于InnoDB 存储引擎来说:
.frm 后缀的文件存储的是表结构。
.ibd 后缀的文件存放索引文件和数据(需要开启innodb_file_per_table 参数)
因此,当你对一张表建立索引时,索引文件的大小也会改变,当你数据表中的数据因为增删改变化时,索引文件也会变化的,只不过MySQL会自动维护索引,这个过程不需要你介入,这也是为什么不恰当的索引会影响MySQL性能的原因。
下面是一种可能的索引方式示例:
左边是数据表,最左边是数据记录的物理地址。
为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针。这样就可以运用二叉查找在一定复杂度内找到相应的数据,从而快速的检索出符合条件的记录。
优势:
劣势:
mysql中不同表的相同字段索引是可以重名的,因为索引文件一表一个;
命名规则:
普通索引:idx_字段名
唯一索引:ux_字段名
我们平时说的索引,如果没有特别指明,都是B树(多路搜索树,并不一定是二叉的)结构组织的索引。 其中聚簇索引,覆盖索引,复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引。当然,除了B+树这种类型的索引外,还有哈希索引(hash index)等 。
这是这基本的索引,它没有任何限制,MyISAM 中默认的 B-tree 类型的索引,基本的索引类型,没有唯一性的限制,允许为NULL值。
# 直接创建索引
CREATE INDEX index_name ON table(column(length))
# 修改表结构的方式添加索引
ALTER TABLE table_name ADD INDEX index_name (column(length))
# 创建表的时候同时创建索引
CREATE TABLE table_name ( \*,INDEX index_name title(length))
# 删除索引
DROP INDEX index_name ON table
与普通索引一致,不同的是索引值必须唯一,允许有空值
# 直接创建索引
CREATE UNIQUE INDEX index_name ON table(column(length))
# 修改表结构的方式添加索引
ALTER TABLE table_name ADD UNIQUE INDEX index_name (column(length))
# 创建表的时候同时创建索引
CREATE TABLE table_name ( \*,UNIQUE index_name title(length))
FULLTEXT 索引仅 MyISAM 引擎支持 他们可以从CHAR、VARCHAR或TEXT列中作为CREATE TABLE语句的一部分被创建,或是随后使用ALTER TABLE 或CREATE INDEX被添加,不过切记对于大容量的数据表,生成全文索引是一个非常消耗时间非常消耗硬盘空间的做法
# 直接创建索引
CREATE FULLTEXT INDEX index_content ON article(content)
# 修改表结构的方式添加索引
ALTER TABLE article ADD FULLTEXT index_content(content)
# 创建表的时候同时创建索引
CREATE TABLE table_name ( \*,FULLTEXT (content))
平时用的SQL查询语句一般都有比较多的限制条件,所以为了进一步榨取MySQL的效率,就要考虑建立组合索引。
ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
建立这样的组合索引,其实是相当于分别建立了下面两组组合索引: –title,time–title
数据列不允许重复,不允许为NULL,一个表只能有一个主键。
ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
show index from 表名
show keys from 表名
desc 表名
上面说到,索引文件时按照不同的数据结构来存储的,数据结构的不同也产生了不同的索引类型,常见的索引类型包括
B-Tree索引、哈希索引、空间数据索引(R-Tree) 、全文索引
B-Tree索引是最常用的一种索引,如果没有指定特定的类型,那么多半就是B-Tree索引,事实上,很多搜索引擎使用的是它的变种B+Tree,这是对B-Tree的一个优化
绝大多数的存储引擎,比如MyISAM和InnoDB都支持这种索引,因此说它是应用最广泛,最常用的一种索引方式,但是不同的存储引擎在具体实现时会稍有不同,比如MyISAM会使用前缀压缩的方式对索引进行压缩,InnoDB则不会。B-tree系统,可理解为”排好序的快速查找结构”.
下图展示了B-Tree索引是如何存储被索引的数据的:
说明:
左图是一个包含三列的数据表,右图则展示了数据是如何被索引的。
可以看出B-Tree是对索引列是按照顺序存储的,每个叶子节点指向被索引的数据,这也是B-Tree索引支持范围查找数据的原因。
相比于B-Tree索引,哈希索引的实现就比较简单了,它是基于哈希表来实现的,对于要索引的列,存储引擎会计算出一一对应的哈希码,然后把哈希码存放在哈希表中作为key,value值是指向该行数据的指针。
下图是简单的原理展示:
说明:
左边紫色图表示一个二列的数据表。
中间表示对fname列进行哈希索引,计算出哈希值。
右边绿色图表示把生成的哈希值存放于哈希表中。
当我们执行以下查询时:
select * from testTable where fname = "mary";
MySQL会首先计算查询条件mary的哈希值,然后到哈希表中去找该哈希值,如果找到了根据对应的指针也就找到了需要寻找的数据行。
哈希表的优势与限制:
在memory表里,默认是hash索引, 只需比对哈希值,因此速度非常快,理论查询时间复杂度为O(1),性能优势明显;
因此,哈希索引虽然速度快,但其实使用很受限,只适用于某些特殊的场合。
空间索引可用于地理数据存储,它需要GIS相关函数的支持,由于MySQL的GIS支持并不完善,所以该索引方式在MySQL中很少有人使用。
在MySQL中,索引是在存储引擎中实现的,并不是所有的存储引擎都支持所有的索引类型,比如哈希索引,MyISAM和InnoDB是不支持的;同样,即使对于同一类型的索引,不同的存储引擎实现的方式也可能是不同的,比如MyISAM和InnoDB对B-Tree索引,具体的实现是有差别的。
总结: