1.避免使用 select *

  会进行全表扫描,不能有效利用索引

  增大了数据库服务器的负担

  增加了数据库与应用程序之间的网络IO开销

2.比较运算符能用 = 就不用 <> 

  增加索引的命中率

3.知道有几条查询结果的情况下,使用 limit N 

  避免全表扫描

4.为列选择合适的数据类型

  占用空间越少越好

5.将大的delete、update、insert变成多个小查询

  性能和数据控制更好

6.获得相同结果集的查询,要保持SQL语句前后一致

7.where子句、order by子句、join子句的列尽量被索引

8.使用 EXPLAIN 检查索引使用情况及扫描的行

  通过检查,创建适当的索引,优化查询

eg:

mysql> explain select id,name,type from api_assets where file_id=5;
+----+-----------+------------+------------+------+----------------+----------------+---------+-------+------+----------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-----------+------------+------------+------+----------------+----------------+---------+-------+------+----------+
| 1 | SIMPLE | api_assets | NULL | ref | file_id_normal | file_id_normal | 4 | const | 105 | 100 | NULL |
+----+-----------+------------+------------+------+----------------+----------------+---------+-------+------+----------+

mysql> explain select id,name,type from api_assets where type like '%window%';
+----+-----------+------------+------------+------+---------------+------+---------+------+------+----------+----------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-----------+------------+------------+------+---------------+------+---------+------+------+----------+----------+
| 1 | SIMPLE | api_assets | NULL | ALL | NULL | NULL | NULL | NULL | 2242 | 11.11 | Using where |
+----+-----------+------------+------------+------+---------------+------+---------+------+------+----------+----------+
各字段的含义

(1)id

  select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序

  有3种情况:

    id相同:执行顺序由上至下 

    id不同:如果是子查询,id的序号会递增,id越大优先级越高,越先被执行

    id既有相同也有不同:相同的id是一组。同一组,从上往下顺序执行;不同组,id越大优先级越高,越先被执行

(2)select_type 

  查询的类型,有:

    SIMPLE:简单查询

    PRIMARY:复杂查询中的主查询。查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARY

    SUBQUERY: 在SELECT或WHERE列表中包含了子查询

    UNION :联合查询。若第二个SELECT出现在UNION之后,则被标记为UNION

    UNION RESULT:联合结果。从UNION表获取结果的SELECT

    DERIVED:衍生查询,一般为产生的临时表。在FROM列表中包含的子查询被标记为DERIVED;若UNION包含在FROM子句的子查询中,外层SELECT将被标记为DERIVED

(3)table 

  查询的表

(4)partitions 

  匹配的分区,非分区表的值为NULL

(5)type 

  关联类型或者访问类型


说明

NULL

在执行阶段不需要访问表

system

const连接类型的一种特例,表仅有一行满足条件

const

通过索引直接找到一个匹配行,一般主键索引的时候

eq_ref

唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。 常见于主键或唯一索引扫描

ref

非唯一性索引扫描,返回匹配某个单独值的所有行。常见于使用非唯一索引即唯一索引的非唯一前缀进行的查找

fulltext

使用全文索引。一般用到的索引都是B树

ref_or_null

同ref,但是添加了MySQL可以专门搜索包含NULL值的行

index_merge

使用了索引合并优化方法

unique_subquery

可以替换IN子查询的ref

index_subquery

类似于unique_subquery。可以替换IN子查询

range

只检索给定范围的行,使用一个索引来选择行

index

利用到了索引,有可能有其它排序,where 或者 group by 等

all

全表扫描,没有使用到索引

 

  结果值从好到坏依次是:NULL>system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL  

  得保证查询至少达到range级别,最好能达到ref

(6)possible_keys 

  可能使用的索引,不一定被查询实际使用

(7)key 

  实际使用的索引,如果为NULL,则没有使用索引

(8)key_len 

  索引中使用的字节数,长度越短越好。当 key 列的值为 NULL 时,则该列也是 NULL

(9)ref 

  哪些字段或者常量被用来和 key 配合从表中查询记录出来

(10)rows 

  找到所需的记录所需要读取的行数,用的越少越好 

(11)filtered 

  根据条件过滤的表行的估计百分比,和 rows 相乘,表示和查询计划里前一个表关联的行数

(12)Extra 

  额外信息,常见的值有

Using index:使用覆盖索引,表示查询索引就可查到所需数据,不用扫描表数据文件

Using Where:在存储引擎检索行后再进行过滤,使用了 where 从句来限制哪些行将与下一张表匹配或者是返回给用户

Using temporary:在查询结果排序时会使用一个临时表,一般出现于排序、分组和多表 join 的情况

Using filesort:对结果使用一个外部索引排序

  注:

    有Using filesort或Using temporary的话,就必须要优化了