SQL 索引与执行计划

Posted 江湖@小小白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL 索引与执行计划相关的知识,希望对你有一定的参考价值。

SQL 索引与执行计划

1. 索引的分类

​ 单值索引:一个索引只包含单个列,一个表可以有多个单列索引。

​ 唯一索引:索引的值必须唯一,但允许有空值(null)。

​ 复合索引:一个索引包含多个列。

注:一张表建立的索引最好不要超过5个。

2. 索引基本语法


1. 创建索引 [UNIQUE] 可以省略

2. 如果只写一个字段就是单值索引,写多个字段就是复合索引
	create [UNIQUE] INDEX indexName ON 表名(字段名(length));
	
3. 删除索引
	DROP INDEX 索引名称 ON 表名;

4. 查看索引
	SHOW INDEX FROM 表名 \\G; 加上 \\G 就可以以列的形式查看,不加 \\G 以表的形式查看。

注:
	查看执行计划:EXPLAIN * FROM 表名;

	查看索引:show index from 数据库名.表名 where column_name like '列名';

	建立普通索引:CREATE INDEX index_name(索引名称) ON 表名 (字段名) ;

	删除索引:drop index index_name(索引名) on 表名 ;
	
2.1 使用索引的注意事项
  1. 要在经常搜索的列上加索引,这样可以加快搜索的速度。
  2. 在经常使用使用 where 字句的列上加索引,加快条件的判断速度。
  3. 要在经常排序的列上加索引,因为索引已经是排好序的,这样查询可以利用索引的排序,加快查询的时间。
  4. 对于中到大型表索引都是非常有效的,但是对于特大型表的话维护开销很大,不适合建立索引。
  5. 索引加在经常用来连接的列上,这些列主要是一些外键,可以加快连接的速度。
  6. 避免where字句中对字段加函数,这样会造成索引失效,导致无法命中索引。
  7. 在使用 InnoDB 时使用与1业务无关的自增主键作为主键,即使用逻辑主键,而不要使用业务主键。
  8. 将打算加索引的列设置为**NOT NULL **,否则将导致引擎放弃使用索引而进行全表扫描。
  9. 删除长期未使用的索引,不用的索引继续存在的话会造成不必要的性能损耗,mysql5.7可以通过查询sys库的chema_unused_indexes视图来查询哪些索引从未被使用。

3. 查看执行计划

3.1 EXPLAIN

​ SQL的执行计划,使用EXPLAIN关键字可以模拟优化器执行 SQL 查询语句,从而知道MySQL是如何处理SQL语句的。

语法:explain + SQL
EXPLAIN SELECT
*
FROM
work_code_st wcs
WHERE
wcs.commit_added_lines > 0;

3.2 使用 EXPLAIN 能够查看的信息

​ 可以查看以下信息:


id:表的读取顺序,id 越大优先级越高,越先被执行。

select_type:数据读取操作的操作类型。

possible_keys:哪些索引可以使用。

key:哪些索引被实际使用。

ref:表之间的引用。

rows:每张表有多少行被优化器查询,根据表统计信息及索引选用情况,大致估算出找到所需的记录需要读取的行数。

type:访问类型排列。从最好到最差依次是:
system > const > eq_ref > ref > range > index > ALL。
除了 ALL 没有用到索引,其他级别都用到索引了。一般来说,得保证查询至少达到 range 级别,最好达到 ref。

    system:
    表只有一行记录(等于系统表),这是const类型的特例,平时不会出现,这个也可以忽略不计。
    
    const:表示通过索引一次就找到了,const 用于比较 primary key 或者 unique 索引。因为只匹配一行数据,所以很快。如将主键置于where 列表中,MySQL 就能将该查询转化为一个常量。
    
    eq_ref:唯一性索引扫描,读取本表中和关联表表中的每行组合成的一行,查出来只有一条记录。除 了 system 和 const 类型之外, 这是最好的联接类型。
    
    ref:非唯一性索引扫描,返回本表和关联表某个值匹配的所有行,查出来有多条记录;显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值。
    
    range:只检索给定范围的行,一般就是在 WHER E语句中出现了 BETWEEN< >in 等的查询。这种范围扫描索引比全表扫描要好,因为它只需要开始于索引树的某一点,而结束于另一点,不用扫描全部索引。
    
    indexFull Index Scan,全索引扫描,indexALL的区别为 index 类型只遍历索引树。
    也就是说虽然 ALLindex 都是读全表,但是 index 是从索引中读的,ALL 是从磁盘中读取的。
    
    ALLFull Table Scan,没有用到索引,全表扫描。
  


以上是关于SQL 索引与执行计划的主要内容,如果未能解决你的问题,请参考以下文章

如何根据执行计划,判断Mysql语句是不是走索引

SQL SERVER执行计划和索引优化基础

SQL Server索引的执行计划

SQL Server 堆heap 非聚集索引 Nonclustered index 行号键查找RID loopup结合执行计划过程详解

MySQL优化必备之执行计划explain,索引基本知识,索引数据结构推演

不会看 Explain执行计划,简历敢写 SQL 优化?