在目前这个大数据,大流量时代,我们的网站不光流量大,数据量也会非常的巨大。在巨大的数据量中精确找出我们需要的数据,这个对我们数据库压力比较大。而我们在不考虑进行分库分表的操作时,进行SQL语句优化是一个很好的解决办法,下面介绍explain
关键词分析SQL语句,及使用索引进行优化查询。
explain
关键字使用
explain
使用格式
EXPLAIN SELECT
*
FROM
SCORE
WHERE
CNO = '3-105'
AND DEGREE > (
SELECT
DEGREE
FROM
SCORE
WHERE
SNO = 109
)
查询结果
id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra |
---|---|---|---|---|---|---|---|---|---|
1 | PRIMARY | SCORE | ALL | null | null | null | null | 12 | Using where |
2 | SUBQUERY | SCORE | ALL | null | null | null | null | 12 | Using where |
explain
表格各个属性分析
id
:select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序
id相同时,执行顺序由上至下
id不同时,如果是子查询,序号id会递增,id值越大优先级越高,越先被执行,在所有组中,id值越大优先级越高
select_type
:查询类别,主要是区别普通查询,联合查询,子查询等复杂查询
simple
简单查询,不包含子查询
primary
:包含子查询,为最外层查询
subquery
:子查询
derived
:衍生表,虚拟表
union
:出现union关键字
union select
:在union结果中查询
table
:查询的表名
type
:执行计划包含的信息,显示查询使用了何种类型
type类型从最好到最差
system > const > eq_ref > ref > range >index > all
system
:表中只有一条记录(等于系统表),这是const
类型的特例,平时不会出现,这个可以忽略不计。
const
:表示通过索引一次就找到了,const
用于比较primary key
或者union
索引,因为只匹配一行数据,所以很快,如将主键置于where中。
eq_ref
:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见主键或者唯一索引扫描
ref
:非唯一索引扫描,返回匹配条件的所有行。本质上也是一种索引,他返回所有匹配某个单独值得所有行,然而,他可能会找到多个符合条件得行,所以他应该属于查找和扫描得混合体。
range
:只检索给定范围的行,使用索引来选择行。key列显示使用了哪些索引,一般就在你的where语句中出现了between、、in等查询,这种范围扫描比全表扫描要好,因为它只需要开始于索引的某一个点,而结束于某一个点,不用全表扫描。
index
:full index scan,index
和all
的区别为index
类型只遍历索引树。这通常比all
快,因为索引文件通常比数据文件小(也就是说虽然all
和index
都是全表扫描,但是index
是从索引文件中进行扫描,all
是通过硬盘中读取的)
all
:全表扫描
possible_keys
:显示可能应用于查询的索引,一个或者多个。查询涉及到字段存在索引,则将索引列出,但不一定在查询中使用。
key
:实际查询使用的索引。如果为null
,则没有用到索引,若使用到了覆盖索引,则该索引只出现在key
列表中。
key_len
:显示索引中使用的字节数,可通过该列计算查询中使用到索引长度。在不损失精度下,长度越短越好。key_len
显示的值为索引字段的最大长度,并非实际使用长度,即key_len
是根据表定义计算而得,不是通过表内检索出得。
ref
:显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或者常量被用于查找索引列上值。
rows
:根据表统计信息及索引选用情况,大致估算出找到所需的记录需要读取的行数
extra
:不适合在其他列中显示,但又十分重要的信息
using filesort
:说明MySQL会对数据使用一个外部的索引排序,而不是按照表内索引进行读取。MySQL中无法利用索引完成排序操作称之为文件排序
。如果出现这种情况,查询将会非常的慢
using temporary
:说明使用临时表保存中间结果,MySQL在对查询结果进行排序时,使用临时表。常见于排序order by
和group by
。出现这种情况查询会非常慢。
using index
:表示相应的select操作中使用覆盖索引(covering index),避免访问数据行,效率很好!如果同时出现using where
,表明索引被用来执行索引值查找;如果没有同时出现using where
,表明索引用来读取非执行查找动作。
using where
:使用where
关键字查找
impossible where
:子句的值总的false,不能用来获取任何元组
索引优化案例
单表建立索引,查询的字段不要出现范围否则会出现索引失效的情况
两个表连接查询建立索引,索引一般建在从表上,左连接,建立在右边;右连接,建立在左边。
索引失效情况(应该避免)
全值匹配我最爱(查询条件完全符合索引顺序)
最佳左前缀法则:如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左列开始并且 不跳过索引列(类别火车,火车头)
不能在所有列上做任何操作(计算,函数,(自动or手动)类型转换),会导致索引失效,导致全表扫描
存储引擎不能使用索引中范围条件右边的列
尽量使用覆盖索引(只访问索引的查询),减少select *
在使用不等于(!= 或者)的时候无法使用索引导致全表扫描
is null 或者is not null 也无法使用索引
like以通配符开头(’%abcd’),MySQL索引会失效会变成全表扫描
字符串不加单引号索引也会失效
少用or,用了它连接会导致索引失效
阿里巴巴规范
推荐】:SQL性能优化的目标:至少要达到rang
级别,要求是ref
级别,如果可以是consts
最好。consts
单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。ref
指的是使用普通的索引(normal index)rang
对索引进行范围检索