你有没有这样的情况。
面对一个你没怎么写过的、复杂的业务,你构思了很久,终于开始敲下了第一段代码。
写的过程迷迷糊糊,有的时候还能把自己搞晕了。
但你还是终于把它写完了。
但是点击一运行,完了,有bug。
怎么办?
debug的方式有很多,控制台打印是一种。
通过控制台打印的信息,我们能根据反馈去修改代码,直到代码能正常运行为止。
其实建索引也是一样的。
上篇帖子《浅谈sql索引》,说过索引的难点在于针对一个具体的表去做出最合适的索引。
因为这不只要看你表里有什么内容,更多要看你的业务,你的业务会经常根据哪些关键词查找。
代码我们可以天天写,索引不能天天建吧。
所以多数情况下,因为不熟悉,我们一开始建立的索引往往都不是最好的,唯有根据反馈去调整索引,才能做出一个最合适这个表的索引。
怎么做性能分析使用EXPLAIN关键字!
使用EXPLAIN关键字可以知道MySQL是如何处理你的SQL语句的,分析你的查询语句或是表结构的性能瓶颈。
但EXPLAIN并不能直接反馈我们建的索引的好坏。
用法是这样的,我们建好了索引,拿着业务中最常用的几句SQL语句来EXPLAIN一下,如果反馈的效果好,那么建立的索引就是最适合这个表的,反之则需要改进。
要不改索引,要不改SQL。
EXPLAIN玩法 语句explain 要查看的sql语句(横表)或explain 要查看的sql语句\G(竖表)
一个具体的例子 各个字段解释从上图中我们可以看到,explain出来的信息有以下字段:
id select_type table type possible_keys key key_len ref rows Extra你仔细看看,这么长是不是有点像工资条?
其中各个字段代表的意思是这样的:
id: 查看表的读取顺序。
咱们上图中的例子只查询了一个表,但若是多表联合查询,则有: id相同的话,执行顺序由上至下; id不同的话,id值越大优先级越高;
select_type: 显示区别联合查询、子查询、普通查询等。
以下为其可能的值,以及对应所代表的信息: SIMPLE -- 简单的select查询,不包含子查询或union; PRIMARY -- 查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARY; SUBQUERY -- 在select或where包含的子查询; DERIVED -- 在from列表包含的子查询被标记为DERIVED(衍生),MySQL会递归执行这些子查询,把结果放在临时表里; UNION -- 若第二个select出现在union后,则被标记为union;若union包含在from子句的子查询中,外层select将被标记为:DERIVED; UNION RESULT -- 从union表获取结果的select;
table: 显示表名。
type: 显示查询用了何种类型。
以下为其可能的值,以及对应所代表的信息: system -- 表只有一行记录(等于系统表),这是const类型的特例,平时不会出现,可以忽略不记。 const -- 表示通过索引一次就找到了,const用于比较primary key(主键)或者unique(唯一)索引。因为只匹配一行数据,所以很快,如果将主键置于where列表中,mysql就能将该查询转换到一个常量。 eq_ref -- 唯一性扫描索引,对于每个索引键,表中**刚好只**有一条记录与之匹配。常用于主键或唯一索引扫描。 ref -- 非唯一性扫描索引,返回匹配某个单独值的所有行。上面`eq_ref`的多值情况。如where age=1,age=1的数据刚好只有一行,便显示eq_ref,age=1的数据有多行,便显示ref。 range -- 只检索给定范围的行,使用一个索引来选择行。如果type列的值为`range`,key列便会显示使用了哪个索引。一般就是在where语句中出现了between、<、>、in等的查询。这种范围扫描查询比全表扫描要好。 index -- Full Index Scan(扫描全部索引),index与ALL区别为index类型只遍历索引树。都是读全表,但是index是从索引中读取,all是从硬盘中读,而且索引文件通常比数据文件小。 all -- Full Table Scan(扫描全表),遍历全表来找到匹配的行,即索引完全没用上。 从最好到最差依次是:system>const>eq_ref>ref>range>index>ALL 细节: 1. type 是 ALL,当数据到达百万以上一定要优化。 2. 一般来说,如果要优化得保证查询至少达到range级别,最好达到ref。
possible_keys和key
possible_key: 显示可能应用在这张表中的索引,一个或多个。理论上可能被使用的索引,但不一定被查询实际使用。 key: 实际使用的索引,如果为null,则没有使用索引。 这两列有四种情况: 1. possible_key有值,key有值:正常,有的时候前者有多个值但后者只有一个也正常。 2. possible_key有值,key无值:**索引失效了,出现问题了**。 3. possible_key无值,key有值:条件查询(如where)没有用到索引或没有条件查询,但查询的列(select后面的字段)刚好顺序、数量和索引一致。 4. possible_key无值,key无值:正常,就是你没建索引。