Mysql索引详解及优化(key和index区别)

MySQL索引的概念
    索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里全部记录的引用指针。更通俗的说,数据库索引比如是一本书前面的目录,能加快数据库的查询速度。
    索引分为聚簇索引和非聚簇索引两种,聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引就不同了;聚簇索引能提升多行检索的速度,而非聚簇索引对于单行的检索很快
    要注意的是,创建太多的索引将会影响更新和插入的速度,由于它须要一样更新每一个索引文件。对于一个常常须要更新和插入的表格,就没有必要为一个不多使用的where字句单独创建索引了,对于比较小的表,排序的开销不会很大,也没有必要创建另外的索引。html

1. 普通索引

    普通索引(由关键字KEY或INDEX定义的索引)的惟一任务是加快对数据的访问速度。所以,应该只为那些最常常出如今查询条件(WHERE column = ...)或排序条件(ORDER BY column)中的数据列建立索引。只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来建立索引。 mysql

[sql]  view plain  copy 在CODE上查看代码片派生到个人代码片
  1. –直接建立索引(length表示使用名称前1ength个字符)  
  2. CREATE INDEX index_name ON table_name(column_name(length))  
  3. –修改表结构的方式添加索引  
  4. ALTER TABLE table_name ADD INDEX 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. INDEX index_name (title)  
  11. ) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;  
  12. –删除索引  
  13. DROP INDEX index_name ON table_name;  
  14.   
  15. 创建复合索引 。  
  16. CREATE INDEX mytable_categoryid_userid ON mytable (category_id,user_id);  
  17.   注意命名时的习惯了吗?使用"表名_字段1名_字段2名"的方式  

2. 惟一索引

    与普通索引相似,不一样的就是:索引列的值必须惟一,但容许有空值(注意和主键不一样)。若是是组合索引,则列值的组合必须惟一,建立方法和普通索引相似。
    若是能肯定某个数据列将只包含彼此各不相同的值,在为这个数据列建立索引的时候就应该用关键字UNIQUE把它定义为一个惟一索引。这么作的好处:一是简化了MySQL对这个索引的管理工做,这个索引也所以而变得更有效率;二是MySQL会在有新记录插入数据表时,自动检查新记录的这个字段的值是否已经在某个记录的这个字段里出现过了;若是是,MySQL将拒绝插入那条新记录。也就是说,惟一索引能够保证数据记录的惟一性。事实上,在许多场合,人们建立惟一索引的目的每每不是为了提升访问速度,而只是为了不数据出现重复。 sql

[sql]  view plain  copy 在CODE上查看代码片派生到个人代码片
  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. );  

3.主索引 

  在前面已经反复屡次强调过:必须为主键字段建立一个索引,这个索引就是所谓的"主索引"。主索引与惟一索引的惟一区别是:前者在定义时使用的关键字是PRIMARY而不是UNIQUE。 数据库

4.外键索引 

  若是为某个外键字段定义了一个外键约束条件,MySQL就会定义一个内部索引来帮助本身以最有效率的方式去管理和使用外键约束条件。 服务器

5. 全文索引(FULLTEXT)

      MySQL从3.23.23版开始支持全文索引和全文检索,fulltext索引仅可用于 MyISAM 表;他们能够从CHAR、VARCHAR或TEXT列中做为CREATE TABLE语句的一部分被建立,或是随后使用ALTER TABLE 或CREATE INDEX被添加。////对于较大的数据集,将你的资料输入一个没有FULLTEXT索引的表中,而后建立索引,其速度比把资料输入现有FULLTEXT索引的速度更为快。不过切记对于大容量的数据表,生成全文索引是一个很是消耗时间很是消耗硬盘空间的作法。
       文本字段上的普通索引只能加快对出如今字段内容最前面的字符串(也就是字段内容开头的字符)进行检索操做。若是字段里存放的是由几个、甚至是多个单词构成的较大段文字,普通索引就没什么做用了。这种检索每每以LIKE %word%的形式出现,这对MySQL来讲很复杂,若是须要处理的数据量很大,响应时间就会很长。 
  这类场合正是全文索引(full-text index)能够大显身手的地方。在生成这种类型的索引时,MySQL将把在文本中出现的全部单词建立为一份清单,查询操做将根据这份清单去检索有关的数据记录。全文索引便可以随数据表一同建立,也能够等往后有必要时再使用下面这条命令添加: 
  ALTER TABLE table_name ADD FULLTEXT(column1, column2) 
  有了全文索引,就能够用SELECT查询命令去检索那些包含着一个或多个给定单词的数据记录了。下面是这类查询命令的基本语法: 
  SELECT * FROM table_name 
  WHERE MATCH(column1, column2) AGAINST('word1', 'word2', 'word3') 
  上面这条命令将把column1和column2字段里有word一、word2和word3的数据记录所有查询出来。 oracle

[sql]  view plain  copy 在CODE上查看代码片派生到个人代码片
  1. –建立表的适合添加全文索引  
  2. CREATE TABLE `table_name` (  
  3. `id` int(11) NOT NULL AUTO_INCREMENT ,  
  4. `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL ,  
  5. PRIMARY KEY (`id`),  
  6. FULLTEXT (content)  
  7. );  
  8. –修改表结构添加全文索引  
  9. ALTER TABLE table_name ADD FULLTEXT index_name(column_name)  
  10. –直接建立索引  
  11. CREATE FULLTEXT INDEX index_name ON table_name (column_name)  

6. 单列索引、多列索引

    多个单列索引与单个多列索引的查询效果不一样,由于执行查询时,MySQL只能使用一个索引,会从多个索引中选择一个限制最为严格的索引。数据库设计

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

    平时用的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;

性能

MySQL索引的优化

    上面都在说使用索引的好处,但过多的使用索引将会形成滥用。所以索引也会有它的缺点:虽然索引大大提升了查询速度,同时却会下降更新表的速度,如对表进行INSERT、UPDATE和DELETE。由于更新表时,MySQL不只要保存数据,还要保存一下索引文件。创建索引会占用磁盘空间的索引文件。通常状况这个问题不太严重,但若是你在一个大表上建立了多种组合索引,索引文件的会膨胀很快。索引只是提升效率的一个因素,若是你的MySQL有大数据量的表,就须要花时间研究创建最优秀的索引,或优化查询语句。下面是一些总结以及收藏的MySQL索引的注意事项和优化方法。测试

1. 什么时候使用汇集索引或非汇集索引?

动做描述 使用汇集索引 使用非汇集索引
列常常被分组排序 使用 使用
返回某范围内的数据 使用 不使用
一个或极少不一样值 不使用 不使用
小数目的不一样值 使用 不使用
大数目的不一样值 不使用 使用
频繁更新的列 不使用 使用
外键列 使用 使用
主键列 使用 使用
频繁修改索引列 不使用 使用

2. 索引不会包含有NULL值的列

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

3. 使用短索引

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

4. 索引列排序

    MySQL查询只使用一个索引,所以若是where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。所以数据库默认排序能够符合要求的状况下不要使用排序操做;尽可能不要包含多个列的排序,若是须要最好给这些列建立复合索引。

5. like语句操做

    通常状况下不鼓励使用like操做,若是非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可使用索引。

6. 不要在列上进行运算

    例如:select * from users where YEAR(adddate)<2007,将在每一个行上进行运算,这将致使索引失效而进行全表扫描,所以咱们能够改为:select * from users where adddate<’2007-01-01′。关于这一点能够围观:一个单引号引起的MYSQL性能损失。
    
    最后总结一下,MySQL只对一下操做符才使用索引:<,<=,=,>,>=,between,in,以及某些时候的like(不以通配符%或_开头的情形)。而理论上每张表里面最多可建立16个索引,不过除非是数据量真的不少,不然过多的使用索引也不是那么好玩的,好比我刚才针对text类型的字段建立索引的时候,系统差点就卡死了。

补充EXPLAIN 用法:

    只有当数据库里已经有了足够多的测试数据时,它的性能测试结果才有实际参考价值。若是在测试数据库里只有几百条数据记录,它们每每在执行完第一条查询命令以后就被所有加载到内存里,这将使后续的查询命令都执行得很是快--无论有没有使用索引。只有当数据库里的记录超过了1000条、数据总量也超过了MySQL服务器上的内存总量时,数据库的性能测试结果才有意义。 
  在不肯定应该在哪些数据列上建立索引的时候,人们从EXPLAIN SELECT命令那里每每能够得到一些帮助。这其实只是简单地给一条普通的SELECT命令加一个EXPLAIN关键字做为前缀而已。有了这个关键字,MySQL将不是去执行那条SELECT命令,而是去对它进行分析。MySQL将以表格的形式把查询的执行过程和用到的索引(若是有的话)等信息列出来。 
  在EXPLAIN命令的输出结果里,第1列是从数据库读取的数据表的名字,它们按被读取的前后顺序排列。type列指定了本数据表与其它数据表之间的关联关系(JOIN)。在各类类型的关联关系当中,效率最高的是system,而后依次是const、eq_ref、ref、range、index和All(All的意思是:对应于上一级数据表里的每一条记录,这个数据表里的全部记录都必须被读取一遍--这种状况每每能够用一索引来避免)。 
  possible_keys数据列给出了MySQL在搜索数据记录时可选用的各个索引。key数据列是MySQL实际选用的索引,这个索引按字节计算的长度在key_len数据列里给出。好比说,对于一个INTEGER数据列的索引,这个字节长度将是4。若是用到了复合索引,在key_len数据列里还能够看到MySQL具体使用了它的哪些部分。做为通常规律,key_len数据列里的值越小越好(意思是更快)。 
  ref数据列给出了关联关系中另外一个数据表里的数据列的名字。row数据列是MySQL在执行这个查询时预计会从这个数据表里读出的数据行的个数。row数据列里的全部数字的乘积可让咱们大体了解这个查询须要处理多少组合。

--------------------------------------------------------------------------------------------------------------

8.key和index区别

    mysql的key和index多少有点使人迷惑,这实际上考察对数据库体系结构的了解的。
    1).key 是数据库的物理结构,它包含两层意义,一是约束(偏重于约束和规范数据库的结构完整性),二是索引(辅助查询用的)。包括primary key, unique key, foreign key 等。
  primary key 有两个做用,一是约束做用(constraint),用来规范一个存储主键和惟一性,但同时也在此key上创建了一个index;
  unique key 也有两个做用,一是约束做用(constraint),规范数据的惟一性,但同时也在这个key上创建了一个index;
  foreign key也有两个做用,一是约束做用(constraint),规范数据的引用完整性,但同时也在这个key上创建了一个index;
  可见,mysql的key是同时具备constraint和index的意义,这点和其余数据库表现的可能有区别。(至少在Oracle上创建外键,不会自动创建index),所以建立key也有以下几种方式:
  (1)在字段级以key方式创建, 如 create table t (id int not null primary key);
  (2)在表级以constraint方式创建,如create table t(id int, CONSTRAINT pk_t_id PRIMARY key (id));
  (3)在表级以key方式创建,如create table t(id int, primary key (id));
  其它key建立相似,但无论那种方式,既创建了constraint,又创建了index,只不过index使用的就是这个constraint或key。

    2).index是数据库的物理结构,它只是辅助查询的,它建立时会在另外的表空间(mysql中的innodb表空间)以一个相似目录的结构存储。索引要分类的话,分为前缀索引、全文本索引等;
  所以,索引只是索引,它不会去约束索引的字段的行为(那是key要作的事情)。
  如,create table t(id int, index inx_tx_id  (id));

    3).最后的释疑:
    (1).咱们说索引分类,分为主键索引、惟一索引、普通索引(这才是纯粹的index)等,也是基因而不是把index看做了key。
  好比 create table t(id int, unique index inx_tx_id  (id));  --index看成了key使用
    (2).最重要的也就是,无论如何描述,理解index是纯粹的index,仍是被看成key,看成key时则会有两种意义或起两种做用。

 

 

我有个表,aid为char类型的。
例如
aid
0314 
0314589
0128
0789
031475684
0987

我须要执行一个sql 来找出aid为0314开头的总数
SELECT COUNT(*) AS `count` FROM aid_info WHERE `aid` LIKE '0314%';
aid上有索引,可是仍是比较慢。因而我想用短索引提升速度 alter table  aid_info add index aid(aid(4));
由于我想若是用4位的短索引,上面的记录在索引中应该是:
0314 
0314
0128
0789
0314
0987
我觉得能够更快的找出LIKE '0314%',可是事实更慢了。我想知道这是为何?哪位大师给我讲讲吧。

原文连接:https://www.cnblogs.com/jianmingyuan/p/6740090.html

相关文章
相关标签/搜索