MySQL的索引及优化方案

索引的概念:

通过给字段添加索引可以提高数据的读取速度,提高项目的并发能力和抗压能力。索引优化是mysql中的一种优化方式。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容

索引的分类:

主键索引
当把一张表的某列设置为主键的时候,则该列就是主键索引。
主键是一种唯一性索引,但它必须指定为 primary key,每个表只能有一个主键。
当一张表,把某个列设为主键的时候,则该列就是主键索引

1. **create table a(**  
2. id **int primary key auto_increment,**  
3. **name varchar(20) not null default ''**  
4. );  
5. //这里id就是表的主键  
如果当创建表时没有指定主键索引,也可以在创建表之后添加:
alter table table_name add primary key (column name);

唯一索引
当表的某列被指定为unique约束时,这列就是唯一索引

索引列的所有值都只能出现一次,即必须唯一,值可以为

create table test (

id int primary key auto_increment , 

name varchar(32) unique

)

test表中name就是唯一索引,唯一索引可以有多个null,不能是重复的内容
相比主键索引,主键字段不能为null,也不能重复

普通索引
一般来说,普通索引是先创建表,然后创建普通索引。

基本的索引类型,值可以为空,没有唯一性的限制。

普通索引一般是在建表后再添加的,
		create index 索引名 on table_name(column1,column2);

​		alter table table_name add index 索引名(column1,column2);

全文索引
全文索引,主要是针对文件,比如文章的索引全文索引针对MyISAM有用,针对innodb没有用
​ 如果希望通过关键字的匹配来进行查询过滤,那么就需要基于相似度的查询,而不是原来的精确数值比较。全文索引就是为这种场景设计的。

首先,全文索引主要针对文本文件,

全文索引的版本、存储引擎、数据类型的支持情况

  1. MySQL 5.6 以前的版本,只有 MyISAM 存储引擎支持全文索引;
  2. MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引;
  3. 只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。
1. **create table c(**  
2. id **int primary key auto_increment ,**  
3. title **varchar(20),**  
4. content text,  
5. fulltext(title,content)  
6. )engine=myisam charset utf8;   
7. **insert into c(title,content) values**  
8.('MySQL Tutorial','DBMS stands for DataBase ...'),  
9.('How To Use MySQL Well','After you went through a ...'),  
10.('Optimizing MySQL','In this tutorial we will show ...'),  
11.('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),  
12.('MySQL vs. YourSQL','In the following database comparison ...'),  
13.('MySQL Security','When configured properly, MySQL ...'); 

索引的机制:

为什么我们添加完索引后查询速度为变快?

传统的查询方法,是按照表的顺序遍历的,不论查询几条数据,mysql需要将表的数据从头到尾遍历一遍
在我们添加完索引之后,mysql一般通过btree算法生成一个索引文件,在查询数据库时,找到索引文件进行遍历(折半查找大幅查询效率),找到相应的键从而获取数据

索引的优缺点:

优点:
创建索引可以大大提高系统的性能。

  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
  • 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
  • 可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
  • 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
  • 通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

缺点
也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?这种想法固然有其合理性,然而也有其片面性。虽然,索引有许多优点,但是,为表中的每一个列都增加索引,是非常不明智的。这是因为,增加索引也有许多不利的一个方面。

  • 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
  • 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
  • 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

在哪些表上适合使用索引?
1 .较频繁的作为查询条件字段应该创建索引
2. 唯一性太差的字段不适合创建索引,尽管频繁作为查询条件,例如gender性别字段
3. 更新非常频繁的字段不适合作为索引
4.不会出现在where语句中的字段不该创建索引

总结:
满足以下条件的字段,才应该创建索引.
a: 肯定在where条经常使用
b: 该字段的内容不是唯一的几个值
c: 字段内容不是频繁变化

索引使用原则

1、较频繁的作为查询条件字段应该创建索引
          select * from emp where empno = 1;

2、唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件
          select * from emp where sex = ‘男’

3、更新非常频繁的字段不适合创建索引
          select * from emp where logincount = 1

4、不会出现在WHERE子句中的字段不该创建索引

索引的使用

1. 建立索引

1、create [UNIQUE|FULLTEXT] index index_name on tbl_name (col_name
[(length)] [ASC | DESC] , ……);
2、alter table table_name ADD INDEX [index_name] (index_col_name,…)

2. 删除索引

1、DROP INDEX index_name ON tbl_name;
2、alter table table_name drop index index_name;
注:删除主键(索引)比较特别: alter table t_b drop primary key;

3. 创建普通索引方法

#1 查看student表中有哪些索引
          mysql> show index from student; #查看student表中有哪些索引

#2 创建最基本的的索引
          mysql> create index index_name on student(name(32)); #将student中字段name创建成索引

#3 删除索引的语法
          mysql> drop index index_name on student;

4. 创建唯一索引

注: 它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值
        #1创建索引
        mysql> create unique index index_name on student(name(32));

使用或不使用索引的情况

1. 下列几种情况下有可能使用到索引

  • 对于创建的多列索引,只要查询条件使用了最左边的列,索引一般就会被使用。
  • 对于使用like的查询,查询如果是 ‘%aaa’ 不会使用到索引, ‘aaa%’ 会使用到索引。

2. 下列的表将不使用索引

  • 如果条件中有or,即使其中有条件带索引也不会使用。
  • 对于多列索引,不是使用的第一部分,则不会使用索引。
  • like查询是以%开头
  • 如果列类型是字符串,那一定要在条件中将数据使用引号引用起来。否则不使用索引。(添加时,字符串必须’’)
  • 如果mysql估计使用全表扫描要比使用索引快,则不使用索引。

索引使用注意事项:

1.对于创建的多列索引,只要查询条件使用了最左边的列,索引一般就会被使用。
比如我们对title,content 添加了复合索引
select * from table_name where title = ‘test’;会用到索引
select * from table_name where content = ‘test’;不会用到索引
2.对于使用like的查询,查询如果是 ‘%a’不会使用到索引 ,而 like 'a%'就会用到索引。最前面不能使用%和_这样的变化值
3.如果条件中有or,即使其中有条件带索引也不会使用。
4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来。

各个索引区别:

普通索引:最基本的索引,没有任何限制
唯一索引:与"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。
主键索引:它 是一种特殊的唯一索引,不允许有空值。
全文索引:仅可用于 Myisam (米色母)表(默认表类型,如果执行大量的查询比较适合。),针对较大的数据,生成全文索引很耗时也耗空间。

索引优化策略

前缀索引

1. 前缀索引就是用列的前缀代替整个列作为索引key,当前缀长度合适时,可以做到既使得前缀索引的选择性接近全列索引

2. 同时因为索引key变短而减少了索引文件的大小和维护开销。

3. 一般来说以下情况可以使用前缀索引:

  • 字符串列(varchar,char,text等),需要进行全字段匹配或者前匹配。也就是=‘xxx’ 或者 like ‘xxx%’
  • 字符串本身可能比较长,而且前几个字符就开始不相同。(比如:收件地址、外国人的姓名)

4. MySQL 前缀索引能有效减小索引文件的大小,提高索引的速度。

5. 但是前缀索引也有它的坏处:MySQL 不能在 ORDER BY 或 GROUP BY 中使用前缀索引,也不能把它们用作覆盖索引(Covering Index)。
      
最左前缀原理

#### 1、以下的查询方式都可以用到索引
'''
select * from table where a=1;
select * from table where a=1 and b=2;
select * from table where a=1 and b=2 and c=3;
上面三个查询按照 (a ), (a,b ),(a,b,c )的顺序都可以利用到索引,这就是最左前缀匹配。
'''

#### 2、如果查询语句是:
'''
select * from table where a=1 and c=3; 那么只会用到索引a。
'''

#### 3、这样不会用的索引
'''
select * from table where b=2 and c=3; 因为没有用到最左前缀a,所以这个查询是用户到索引的。
'''

索引优化的方式

# 1、最左前缀匹配原则,上面讲到了
# 2、主键外键一定要建索引
# 3、对 where,on,group by,order by 中出现的列使用索引
# 4、尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,
# 5、为较长的字符串使用前缀索引

'''
# 6、不要过多创建索引, 权衡索引个数与DML之间关系,DML也就是插入、删除数据操作。
    这里需要权衡一个问题,建立索引的目的是为了提高查询效率的,但建立的索引过多,
    会影响插入、删除数据的速度,因为我们修改的表数据,索引也需要进行调整重建
'''

'''
# 7、对于like查询,”%”不要放在前面。
    SELECT * FROMhoudunwangWHEREunameLIKE'后盾%' -- 走索引 
    SELECT * FROMhoudunwangWHEREunameLIKE "%后盾%" -- 不走索引
'''

'''
# 8、查询where条件数据类型不匹配也无法使用索引 
    字符串与数字比较不使用索引; 
    CREATE TABLEa(achar(10)); 
    EXPLAIN SELECT * FROMaWHEREa="1" – 走索引 
    EXPLAIN SELECT * FROM a WHERE a=1 – 不走索引 
    正则表达式不使用索引,这应该很好理解,所以为什么在SQL中很难看到regexp关键字的原因

为什么不建议使用过长的字段作为主键

1. 例如知道了InnoDB的索引实现后,就很容易明白为什么不建议使用过长的字段作为主键

2. 因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。

3. 再例如,用非单调的字段作为主键在InnoDB中不是个好主意,因为InnoDB数据文件本身是一颗B+Tree,

4. 非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。

发布了25 篇原创文章 · 获赞 11 · 访问量 897

猜你喜欢

转载自blog.csdn.net/weixin_45139342/article/details/104594323