概述:mysql
索引(Index)是帮助MySQL高效获取数据的数据结构。算法
索引是以表列为基础的数据库对象,它保存着表中排序的索引列,而且记录了索引列在数据表中的物理存储位置,实现了表中数据的逻辑排序,sql
其主要目的是提升数据库系统的性能,加快数据的查询速度和减小系统的响应时间。数据库
在MySQL中,索引是在存储引擎层而不是服务器层实现的。因此每种存储引擎的索引都不必定彻底相同。服务器
MYSQL目前提供了一下4种索引:数据结构
B-Tree 索引:最多见的索引类型,大部分引擎都支持B树索引。Innodb 存储引擎的 B-Tree 索引实际使用的存储结构其实是 B+树。
HASH 索引:只有Memory引擎支持,使用场景简单。
R-Tree 索引(空间索引):空间索引是MyISAM的一种特殊索引类型,主要用于地理空间数据类型。
Full-text (全文索引):全文索引也是MyISAM的一种特殊索引类型,主要用于全文检索,InnoDB从MYSQL5.6版本提供对全文索引的支持。oracle
B-Tree索引:函数
也就是一般所指的索引。性能
InnoDB使用B+Tree这种数据结构。优化
B+Tree:每个叶子节点都包含指向下一个叶子节点的指针,从而方便叶子节点的范围遍历。
适合查找范围数据。好比:找出全部以I到K开头的名字。
B-Tree索引具体又可分为:
普通索引:
最基本的索引类型。
–直接建立索引 CREATE INDEX index_name ON table(column(length)) –修改表结构的方式添加索引 ALTER TABLE table_name ADD INDEX index_name ON (column(length)) –建立表的时候同时建立索引 CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), INDEX index_name (title(length)) ) –删除索引 DROP INDEX index_name ON table
惟一索引:
索引列的值必须惟一,但容许有空值(注意和主键不一样)。若是是组合索引,则列值的组合必须惟一。
–建立惟一索引 CREATE UNIQUE INDEX indexName ON table(column(length)) –修改表结构 ALTER TABLE table_name ADD UNIQUE indexName ON (column(length)) –建立表的时候直接指定 CREATE TABLE `table` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , `time` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), UNIQUE indexName (title(length)) );
主键索引:
它是一种特殊的惟一索引,不容许有空值。通常是在建表的时候同时建立主键索引。
也能够用 ALTER 命令,但不能用CREATE INDEX语句建立主键索引。
每一个表只能有一个主键。 (主键至关于聚合索引,是查找最快的索引)
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) );
多列索引(组合索引):
ALTER TABLE table_name ADD INDEX indexName( name, address ) ;
对于多列组合的索引,若是删除其中的某列,则该列也会从索引中删除。若是删除组成索引的全部列,则整个索引将被删除。
根据数据的存储方式的不一样,B-Tree索引又可分为汇集索引和非汇集索引:
CREATE CLUSTERED INDEX indexName ON mytable(mycolumn)
InnoDB的汇集索引其实是在同一个结构中保存了B-Tree索引和数据行。
由于没法同时把数据行存放在两个不一样的地方,因此一个表只能有一个汇集索引。
表数据按照索引的顺序来存储的,也就是说索引项的顺序与表中记录的物理顺序一致。
对于汇集索引, 叶子结点即存储了真实的数据行,再也不有另外单独的数据页 。
非汇集索引 :
CREATE UNCLUSTERED INDEX indexName ON mytable(mycolumn)
表数据存储顺序与索引顺序无关。
对于非汇集索引,叶结点包含索引字段值及指向数据页数据行的逻辑指针,其行数量与数据表行数据量一致。
可使用B-Tree索引的查询类型,以多列索引key(last_name, first_name, dob)为例:
B-Tree的一些限制:
哈希索引:
基于哈希表实现,只有精确匹配索引全部列的查询才有效。
由于它对每行中的全部索引列计算出一个哈希码,做为哈希表的键(原理是基于拉链法的解决碰撞的策略)。
在MySQL中只有Memory引擎显式地支持哈希索引,Memory引擎同时也支持B-Tree索引。
InnoDB中的自适应哈希索引:某些索引值使用很是频繁时,会在内存中基于B-Tree索引只上再建立一个hash索引。
哈希索引的一些限制:
空间数据索引(R-Tree):
ALTER TABLE table_name ADD SPATIAL INDEX indexName( line ) ;
MyISAM表支持空间索引,能够用做地理数据存储。
空间索引会从全部维度来索引数据,能够有效地使用任意维度来进行组合查询。
必须使用 GIS 相关的函数来维护数据。
全文索引:
它查找的是文本中的关键词,而不是直接比较索引中的值。
使用 MATCH AGAINST,而不是普通的 WHERE。
–直接建立索引 CREATE FULLTEXT INDEX index_content ON article(content) –修改表结构添加全文索引 ALTER TABLE article ADD FULLTEXT index_content(content)
索引的优势:
建立惟一性索引,保证数据库表中每一行数据的惟一性
大大加快数据的检索速度,这也是建立索引的最主要的缘由
加速表和表之间的链接,特别是在实现数据的参考完整性方面特别有意义。
在使用分组和排序子句进行数据检索时,一样能够显著减小查询中分组和排序的时间。
经过使用索引,能够在查询的过程当中使用优化隐藏器,提升系统的性能。
索引的缺点 :
建立索引和维护索引要耗费时间,这种时间随着数据量的增长而增长
索引须要占物理空间,除了数据表占数据空间以外,每个索引还要占必定的物理空间,若是要创建聚簇索引,那么须要的空间就会更大
当对表中的数据进行增长、删除和修改的时候,索引也要动态的维护,下降了数据的维护速度
应该在这些列上建立索引:
在常常须要搜索的列上,能够加快搜索的速度;
在做为主键的列上,强制该列的惟一性和组织表中数据的排列结构;
在常常用在链接的列上,这些列主要是一些外键,能够加快链接的速度;
在常常须要根据范围进行搜索的列上建立索引,由于索引已经排序,其指定的范围是连续的;
在常常须要排序的列上建立索引,由于索引已经排序,这样查询能够利用索引的排序,加快排序查询时间;
在常用在WHERE子句中的列上面建立索引,加快条件的判断速度。
不该该建立索引的的这些列具备下列特色:
第一,对于那些在查询中不多使用或者参考的列不该该建立索引。这是由于,既然这些列不多使用到,所以有索引或者无索引,并不能提升查询速度。相反,因为增长了索引,反而下降了系统的维护速度和增大了空间需求。
第二,对于那些只有不多数据值的列也不该该增长索引。这是由于,因为这些列的取值不多,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即须要在表中搜索的数据行的比例很大。增长索引,并不能明显加快检索速度。
第三,对于那些定义为text, image和bit数据类型的列不该该增长索引。这是由于,这些列的数据量要么至关大,要么取值不多。
第四,当修改性能远远大于检索性能时,不该该建立索引。这是由于,修改性能和检索性能是互相矛盾的。当增长索引时,会提升检索性能,可是会下降修改性能。当减小索引时,会提升修改性能,下降检索性能。所以,当修改性能远远大于检索性能时,不该该建立索引。
较频繁的做为查询条件的字段应该建立索引
定义有主键的数据列必定要创建索引。由于主键能够加速定位到表中的某一行。
定义有外键的数据列必定要创建索引。外键列一般用于表与表之间的链接,在其上建立索引能够加快表间的链接。
惟一性太差的字段不适合单首创建索引,即便频繁做为查询条件,好比性别只有男,女
更新很是频繁的字段不适合建立索引
不会出如今 WHERE 子句中的字段不应建立索引
表记录比较少,例如一两千条甚至只有几百条记录的表,不必建索引,让查询作全表扫描就行了;
对于定义为text、image和bit数据类型的列不要创建索引。
能够考虑使用索引的主要有 两种类型的列:在where子句中出现的列,在join子句中出现的列,而不是在SELECT关键字后选择列表的列;
使用短索引,若是对字符串列进行索引,应该指定一个前缀长度,可节省大量索引空间,提高查询速度;好比很长的字符串,对前10个或者20个字符进行索引可以节省大量索引空间,也可能会使查询更快。
利用最左前缀:Mysql会一直向右查找直到遇到范围操做(>,<,like、between)就中止匹配。好比a=1 and b=2 and c>3 and d=6;此时若是创建了(a,b,c,d)索引,那么后面的d索引是彻底没有用到,当换成了(a,b,d,c)就能够用到。
MySQL只对一下操做符才使用索引:<,<=,=,>,>=,between,in, 以及某些时候的like(不以通配符%或_开头的情形)。
不要过分索引,只保持所需的索引。每一个额外的索引都要占用额外的磁盘空间,并下降写操做的性能。 在修改表的内容时,索引必须进行更新,有时可能须要重构,所以,索引越多,所花的时间越长。
惟一索引与主键索引的比较:
Hash索引和btree索引的区别: