MySQL索引

什么是索引

在MySQL中,索引(index)也叫作“键(key)”,它是存储引擎用于快速找到记录的一种数据结构。

在mysql中有多种索引类型

  • 主键索引
    也简称主键。它能够提升查询效率,并提供惟一性约束。一张表中只能有一个主键。被标志为自动增加的字段必定是主键,但主键不必定是自动增加。通常把主键定义在无心义的字段上(如:编号),主键的数据类型最好是数值。
  • 普通索引(常规索引(INDEX或KEY))
    普通索引通常是在建表后再添加的
    • 单列索引mysql

      ALTER TABLE `testDB`.`user` 
       ADD INDEX `idx_name`(`name`) USING BTREE
    • 组合索引redis

      ADD INDEX `idx_mult`(`name`, `address`) USING BTREE

    组合索引最左前缀原则
    例如上面咱们建立了一个name, address的组合索引
    select * from user where name = ‘xxx’ 此时,会走索引
    select * from user where address = ‘xxx’ 则不会走索引算法

  • 全文索引
    首先,全文索引主要针对文本文件,好比文章,标题,全文索引只有MyISAM有效(mysql5.6以后InnoDB也支持了全文索引)sql

create table c(  
            id int primary key auto_increment ,  
            title varchar(20),  
            content text,  
            fulltext(title,content)  
       )engine=myisam charset utf8;  
        insert into c(title,content) values  
            ('MySQL Tutorial','DBMS stands for DataBase ...'),  
            ('How To Use MySQL Well','After you went through a ...'),  
            ('Optimizing MySQL','In this tutorial we will show ...'),  
            ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),  
            ('MySQL vs. YourSQL','In the following database comparison ...'),  
            ('MySQL Security','When configured properly, MySQL ...');
  • 惟一索引数据库

    ADD UNIQUE INDEX `idx_unique`(`en_name`);

    主键是一种约束,惟一索引是一种索引,二者在本质上是不一样的。
    主键建立后必定包含一个惟一性索引,惟一性索引并不必定就是主键。
    惟一性索引列容许空值,而主键列不容许为空值。
    主键列在建立时,已经默认为空值 + 惟一索引了。
    主键能够被其余表引用为外键,而惟一索引不能。
    一个表最多只能建立一个主键,但能够建立多个惟一索引。
    主键更适合那些不容易更改的惟一标识,如自动递增列、身份证号等。缓存

MySQL索引方式?

通常有四种索引方式(BTREE,RTREE, HASH ,FULLTEXT)
  • BTREE索引(一种将索引值按必定的算法,存入一个树形的数据结构中)
    MyISAM表数据文件和索引文件是分离的,索引文件仅保存数据记录的磁盘地址
    InnoDB表数据文件自己就是主索引,叶节点data域保存了完整的数据记录
    • B-TREE索引

    • B+TREE索引

    B+Tree相对于B-Tree有几点不一样:
    非叶子节点只存储键值信息。
    全部叶子节点之间都有一个链指针。
    数据记录都存放在叶子节点中。数据结构

  • HASH索引工具

    • 仅支持"=","IN"和"<=>"精确查询,不能使用范围查询:
      因为Hash索引比较的是进行Hash运算以后的Hash值,因此它只能用于等值的过滤,不能用于基于范围的过滤,由于通过相应的Hash算法处理以后的Hash
    • 不支持排序:
      因为Hash索引中存放的是通过Hash计算以后的Hash值,并且Hash值的大小关系并不必定和Hash运算前的键值彻底同样,因此数据库没法利用索引的数据来避免任何排序运算
    • 在任什么时候候都不能避免表扫描:
      因为Hash索引比较的是进行Hash运算以后的Hash值,因此即便取知足某个Hash键值的数据的记录条数,也没法从Hash索引中直接完成查询,仍是要经过访问表中的实际数据进行相应的比较,并获得相应的结果
    • 检索效率高:
      索引的检索能够一次定位,不像B-Tree索引须要从根节点到枝节点,最后才能访问到页节点这样屡次的IO访问,因此Hash索引的查询效率要远高于B-Tree索引
    • 只有Memory引擎支持显式的Hash索引:
      它的Hash是nonunique的,冲突太多时也会影响查找性能。Memory引擎默认的索引类型便是Hash索引,虽然它也支持B-Tree索引
  • R-Tree索引
    R-Tree在MySQL不多使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。性能

  • FULLTEXT索引
    即为全文索引,目前只有MyISAM引擎支持。其能够在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上能够建立全文索引。
    值得一提的是,在数据量较大时候,现将数据放入一个没有全局索引的表中,而后再用CREATE INDEX建立FULLTEXT索引,要比先为一张表创建FULLTEXT而后再将数据写入的速度快不少。
    它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。mysql索引

总结:

(1)对于BTREE这种Mysql默认的索引方式,具备广泛的适用性
(2)因为FULLTEXT对中文支持不是很好,在没有插件的状况下,最好不要使用。其实,一些小的博客应用,只须要在数据采集时,为其创建关键字列表,经过关键字索引,也是一个不错的方法,至少我是常常这么作的。
(3)对于一些搜索引擎级别的应用来讲,FULLTEXT一样不是一个好的处理方法,Mysql的全文索引创建的文件仍是比较大的,并且效率不是很高,即使是使用了中文分词插件,对中文分词支持也只是通常。
   真要碰到这种问题,Apache的Lucene或许是你的选择。
(4)正是由于hash表在处理较小数据量时具备无可比拟的素的优点,因此hash索引很适合作缓存(内存数据库)。如mysql数据库的内存版本Memsql,使用量很普遍的缓存工具Mencached,NoSql数据库redis等,都使用了hash索引这种形式。
   固然,不想学习这些东西的话Mysql的MEMORY引擎也是能够知足这种需求的。

扩展:

索引不会命中的状况:

  • 1.索引没法存储null值

    a.单列索引没法储null值,复合索引没法储全为null的值。
    b.查询时,采用is null条件时,不能利用到索引,只能全表扫描。
    • 为何索引列没法存储Null值?

      a.索引是有序的。NULL值进入索引时,没法肯定其应该放在哪里。(将索引列值进行建树,其中必然涉及到诸多的比较操做,null 值是不肯定值没法比较,没法肯定null出如今索引树的叶子节点位置。) 
      b.若是须要把空值存入索引,方法有二:其一,把NULL值转为一个特定的值,在WHERE中检索时,用该特定值查找。其二,创建一个复合索引。例如 create index ind_a on table(col1,1);
      经过在复合索引中指定一个非空常量值,而使构成索引的列的组合中,不可能出现全空值。 

  • 不适合键值较少的列(重复数据较多的列)

    假如索引列TYPE有5个键值,若是有1万条数据,那么 WHERE TYPE = 1将访问表中的2000个数据块。
    再加上访问索引块,一共要访问大于200个的数据块。
    若是全表扫描,假设10条数据一个数据块,那么只需访问1000个数据块,既然全表扫描访问的数据块少一些,确定就不会利用索引了。

  • 索引失效的几种状况

    1.若是条件中有or,即便其中有条件带索引也不会使用(这也是为何尽可能少用or的缘由),要想使用or,又想让索引生效,只能将or条件中的每一个列都加上索引 2.对于多列索引,不是使用的第一部分,则不会使用索引 3.like查询以%开头(例如where code like '%AB'条件是不会走索引的,而where code like 'AB%'条件是会走索引的) 4.若是列类型是字符串,那必定要在条件中将数据使用引号引用起来,不然不使用索引 5.若是mysql估计使用全表扫描要比使用索引快,则不使用索引

相关文章
相关标签/搜索