MYSQL 索引相关的问题


1:什么是MySql索引

 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。

2:索引的分类

   索引分为聚簇索引和非聚簇索引两种,聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引就不一样了;聚簇索引能提高多行检索的速度,而非聚簇索引对于单行的检索很快、

聚簇索引,实际存储的循序结构与数据存储的物理机构是一致的,所以通常来说物理顺序结构只有一种,那么一个表的聚簇索引也只能有一个,通常默认都是主键,设置了主键,系统默认就为你加上了聚簇索引,当然有人说我不想拿主键作为聚簇索引,我需要用其他字段作为索引,当然这也是可以的,这就需要你在设置主键之前自己手动的先添加上唯一的聚簇索引,然后再设置主键,这样就木有问题啦。
总而言之,聚簇索引是顺序结构与数据存储物理结构一致的一种索引,并且一个表的聚簇索引只能有唯一的一条;

非聚簇索引记录的物理顺序与逻辑顺序没有必然的联系,与数据的存储物理结构没有关系;一个表对应的非聚簇索引可以有多条,根据不同列的约束可以建立不同要求的非聚簇索引;

主键索引、主索引与唯一索引的唯一区别是:前者在定义时使用的关键字是PRIMARY而不是UNIQUE。 

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

  1. –创建唯一索引  
  2. CREATE UNIQUE INDEX index_name ON table_name(column_name)  
  3. –修改表结构  
  4. ALTER TABLE table_name ADD UNIQUE index_name ON (column_name)  
  5. –创建表的时候直接指定  
  6. CREATE TABLE `table_name` (  
  7. `id` int(11) NOT NULL AUTO_INCREMENT ,  
  8. `title` char(255) NOT NULL ,  
  9. PRIMARY KEY (`id`),  
  10. UNIQUE index_name (title)  
  11. );  

外键索引,如果为某个外键字段定义了一个外键约束条件,MySQL就会定义一个内部索引来帮助自己以最有效率的方式去管理和使用外键约束条件。 

 

全文索引(fulltext索引仅可用于 MyISAM 表)、5.6版本之后InnoDB存储引擎开始支持全文索引

  切记:对于大容量的数据表,生成全文索引是一个非常消耗时间非常消耗硬盘空间的做法。

  为什么用全文索引: 文本字段上的普通索引只能加快对出现在字段内容最前面的字符串(也就是字段内容开头的字符)进行检索操作。如果字段里存放的是由几个、甚至是多个单词构成的较大段文字,普通索引就没什么作用了。这种检索往往以LIKE %word%的形式出现,这对MySQL来说很复杂,如果需要处理的数据量很大,响应时间就会很长。 

  怎么用:

  ALTER TABLE table_name ADD FULLTEXT(column1, column2) 
  有了全文索引,就可以用SELECT查询命令去检索那些包含着一个或多个给定单词的数据记录了。下面是这类查询命令的基本语法: 
  SELECT * FROM table_name 
  WHERE MATCH(column1, column2) AGAINST('word1', 'word2', 'word3') 
  上面这条命令将把column1和column2字段里有word1、word2和word3的数据记录全部查询出来。

单列索引、多列索引

  多个单列索引与单个多列索引的查询效果不同,因为执行查询时,MySQL只能使用一个索引,会从多个索引中选择一个限制最为严格的索引。

组合(复合)索引(最左前缀)

平时用的SQL查询语句一般都有比较多的限制条件,所以为了进一步榨取MySQL的效率,就要考虑建立组合索引。例如上表中针对title和time建立一个组合索引:ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))。建立这样的组合索引,其实是相当于分别建立了下面两组组合索引:
–title,time
–title
为什么没有time这样的组合索引呢?这是因为MySQL组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这两列的查询都会用到该组合索引,如下面的几个SQL所示
–使用到上面的索引
SELECT * FROM article WHREE title='测试' AND time=1234567890;
SELECT * FROM article WHREE title='测试';
–不使用上面的索引
SELECT * FROM article WHREE time=1234567890;

3:索引的弊端

  要注意的是,建立太多的索引将会影响更新和插入的速度,因为它需要同样更新每个索引文件。对于一个经常需要更新和插入的表格,就没有必要为一个很少使用的where字句单独建立索引了,对于比较小的表,排序的开销不会很大,也没有必要建立另外的索引。

创建索引时需要对表加锁,因此实际操作中需要在业务空闲期间进行

索引需要占用磁盘空间,因此在创建索引时要考虑到磁盘空间是否足够

4:索引的优势

可以快速检索,减少I/O次数,加快检索速度;根据索引分组和排序,可以加快分组和排序;

5:建立索引的几种方式:

  5.1:建立表的时候建立索引

create table `table_name`{

  id int(11) NOT NULL AUTO_INCREMENT,

  name varchar(255) NOT NULL DEFAULT 'NO NAME' COMMENT 'NAME',

  age int(3)NOT NULL DEFAULT 18 COMMENT 'AGE',

  PRIMARY KEY(id),

  CONSTRAINT pk_id_t PRIMARY KEY(id),

  UNIQUE KEY key_name(id,name,age),

  KEY key_name (name),

  INDEX key_name(age)

}engine=InnoDB AUTO_INCREMENT=903 DEFAULT CHARSET=utf8 COMMENT='PERSON'

5.2:修改表结构的方式添加索引   

  ALTER TABLE table_name ADD INDEX index_name ON (name);

5.3 直接建立索引

  直接创建索引(length表示使用名称前1ength个字符)  

  CREATE INDEX index_name ON table_name(column_name(length)) 

索引注意事项:

    索引不会包含有Null值的列

    只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

   使用短索引

 对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

  like语句操作

一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引

  不要在列上面进行运算

例如:select * from users where YEAR(adddate)<2007,将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成:select * from users where adddate<’2007-01-01′。关于这一点可以围观:一个单引号引发的MYSQL性能损失。

 

     最后总结一下,MySQL只对一下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些时候的like(不以通配符%或_开头的情形)。而理论上每张表里面最多可创建16个索引,不过除非是数据量真的很多,否则过多的使用索引也不是那么好玩的,比如我刚才针对text类型的字段创建索引的时候,系统差点就卡死了。

 

 

key和index区别

key 是数据库的物理结构,它包含两层意义,一是约束(偏重于约束和规范数据库的结构完整性),二是索引(辅助查询用的)。包括primary key, unique key, foreign key 等。

 

index是数据库的物理结构,它只是辅助查询的,它创建时会在另外的表空间(mysql中的innodb表空间)以一个类似目录的结构存储。

索引不会包含有NULL值的列

5.6版本之后InnoDB存储引擎开始支持全文索引