Mysql几种索引类型的区别及适用状况

如你们所知道的,Mysql目前主要有如下几种索引类型:FULLTEXT,HASH,BTREE,RTREE。html

那么,这几种索引有什么功能和性能上的不一样呢?java

FULLTEXTnode

即为全文索引,目前只有MyISAM引擎支持。其能够在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上能够建立全文索引。值得一提的是,在数据量较大时候,现将数据放入一个没有全局索引的表中,而后再用CREATE INDEX建立FULLTEXT索引,要比先为一张表创建FULLTEXT而后再将数据写入的速度快不少。mysql

全文索引并非和MyISAM一块儿诞生的,它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。在没有全文索引以前,这样一个查询语句是要进行遍历数据表操做的,可见,在数据量较大时是极其的耗时的,若是没有异步IO处理,进程将被挟持,很浪费时间,固然这里不对异步IO做进一步讲解,想了解的童鞋,自行谷哥。redis

全文索引的使用方法并不复杂:算法

建立ALTER TABLE table ADD INDEX `FULLINDEX` USING FULLTEXT(`cname1`[,cname2…]);sql

使用SELECT * FROM table WHERE MATCH(cname1[,cname2…]) AGAINST ('word' MODE );数据库

其中, MODE为搜寻方式(IN BOOLEAN MODE ,IN NATURAL LANGUAGE MODE ,IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION / WITH QUERY EXPANSION)。缓存

关于这三种搜寻方式,愚安在这里也很少作交代,简单地说,就是,布尔模式,容许word里含一些特殊字符用于标记一些具体的要求,如+表示必定要有,-表示必定没有,*表示通用匹配符,是否是想起了正则,相似吧;天然语言模式,就是简单的单词匹配;含表达式的天然语言模式,就是先用天然语言模式处理,对返回的结果,再进行表达式匹配。数据结构

对搜索引擎稍微有点了解的同窗,确定知道分词这个概念,FULLTEXT索引也是按照分词原理创建索引的。西文中,大部分为字母文字,分词能够很方便的按照空格进行分割。但很明显,中文不能按照这种方式进行分词。那又怎么办呢?这个向你们介绍一个Mysql的中文分词插件Mysqlcft,有了它,就能够对中文进行分词,想了解的同窗请移步Mysqlcft,固然还有其余的分词插件可使用。

HASH

Hash这个词,能够说,自打咱们开始码的那一天起,就开始不停地见到和使用到了。其实,hash就是一种(key=>value)形式的键值对,如数学中的函数映射,容许多个key对应相同的value,但不容许一个key对应多个value。正是因为这个特性,hash很适合作索引,为某一列或几列创建hash索引,就会利用这一列或几列的值经过必定的算法计算出一个hash值,对应一行或几行数据(这里在概念上和函数映射有区别,不要混淆)。在java语言中,每一个类都有本身的hashcode()方法,没有显示定义的都继承自object类,该方法使得每个对象都是惟一的,在进行对象间equal比较,和序列化传输中起到了很重要的做用。hash的生成方法有不少种,足能够保证hash码的惟一性,例如在MongoDB中,每个document都有系统为其生成的惟一的objectID(包含时间戳,主机散列值,进程PID,和自增ID)也是一种hash的表现。额,我好像扯远了-_-!

因为hash索引能够一次定位,不须要像树形索引那样逐层查找,所以具备极高的效率。那为何还须要其余的树形索引呢?

在这里愚安就不本身总结了。引用下园子里其余大神的文章:来自 14的路 的MySQL的btree索引和hash索引的区别

(1)Hash 索引仅仅能知足"=","IN"和"<=>"查询,不能使用范围查询。
因为 Hash 索引比较的是进行 Hash 运算以后的 Hash 值,因此它只能用于等值的过滤,不能用于基于范围的过滤,由于通过相应的 Hash 算法处理以后的 Hash 值的大小关系,并不能保证和Hash运算前彻底同样。
(2)Hash 索引没法被用来避免数据的排序操做。
因为 Hash 索引中存放的是通过 Hash 计算以后的 Hash 值,并且Hash值的大小关系并不必定和 Hash 运算前的键值彻底同样,因此数据库没法利用索引的数据来避免任何排序运算;
(3)Hash 索引不能利用部分索引键查询。
对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一块儿计算 Hash 值,而不是单独计算 Hash 值,因此经过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也没法被利用。
(4)Hash 索引在任什么时候候都不能避免表扫描。
前面已经知道,Hash 索引是将索引键经过 Hash 运算以后,将 Hash运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,因为不一样索引键存在相同 Hash 值,因此即便取知足某个 Hash 键值的数据的记录条数,也没法从 Hash 索引中直接完成查询,仍是要经过访问表中的实际数据进行相应的比较,并获得相应的结果。
(5)Hash 索引遇到大量Hash值相等的状况后性能并不必定就会比B-Tree索引高。
对于选择性比较低的索引键,若是建立 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会很是麻烦,会浪费屡次表数据的访问,而形成总体性能低下。

 

愚安我稍做补充,讲一下HASH索引的过程,顺便解释下上面的第4,5条:

当咱们为某一列或某几列创建hash索引时(目前就只有MEMORY引擎显式地支持这种索引),会在硬盘上生成相似以下的文件:

hash值  存储地址    
1db54bc745a1 77#45b5 
4bca452157d4 76#4556,77#45cc…

hash值即为经过特定算法由指定列数据计算出来,磁盘地址即为所在数据行存储在硬盘上的地址(也有多是其余存储地址,其实MEMORY会将hash表导入内存)。

这样,当咱们进行WHERE age = 18 时,会将18经过相同的算法计算出一个hash值==>在hash表中找到对应的储存地址==>根据存储地址取得数据

因此,每次查询时都要遍历hash表,直到找到对应的hash值,如(4),数据量大了以后,hash表也会变得庞大起来,性能降低,遍历耗时增长,如(5)。

BTREE

BTREE索引就是一种将索引值按必定的算法,存入一个树形的数据结构中,相信学过数据结构的童鞋都对当初学习二叉树这种数据结构的经历记忆犹新,反正愚安我当时为了软考但是被这玩意儿好好地折腾了一番,不过那次考试好像没怎么考这个。如二叉树同样,每次查询都是从树的入口root开始,依次遍历node,获取leaf。

BTREE在MyISAM里的形式和Innodb稍有不一样

在 Innodb里,有两种形态:一是primary key形态,其leaf node里存放的是数据,并且不只存放了索引键的数据,还存放了其余字段的数据。二是secondary index,其leaf node和普通的BTREE差很少,只是还存放了指向主键的信息.

而在MyISAM里,主键和其余的并无太大区别。不过和Innodb不太同样的地方是在MyISAM里,leaf node里存放的不是主键的信息,而是指向数据文件里的对应数据行的信息.

RTREE

RTREE在mysql不多使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。

相对于BTREE,RTREE的优点在于范围查找.

各类索引的使用状况

(1)对于BTREE这种Mysql默认的索引类型,具备广泛的适用性

(2)因为FULLTEXT对中文支持不是很好,在没有插件的状况下,最好不要使用。其实,一些小的博客应用,只须要在数据采集时,为其创建关键字列表,经过关键字索引,也是一个不错的方法,至少愚安我是常常这么作的。

(3)对于一些搜索引擎级别的应用来讲,FULLTEXT一样不是一个好的处理方法,Mysql的全文索引创建的文件仍是比较大的,并且效率不是很高,即使是使用了中文分词插件,对中文分词支持也只是通常。真要碰到这种问题,Apache的Lucene或许是你的选择。

(4)正是由于hash表在处理较小数据量时具备无可比拟的素的优点,因此hash索引很适合作缓存(内存数据库)。如mysql数据库的内存版本Memsql,使用量很普遍的缓存工具Mencached,NoSql数据库redis等,都使用了hash索引这种形式。固然,不想学习这些东西的话Mysql的MEMORY引擎也是能够知足这种需求的。

(5)至于RTREE,愚安我至今尚未使用过,它具体怎么样,我就不知道了。有RTREE使用经历的同窗,到时能够交流下!

相关文章
相关标签/搜索