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的话,就必须要优化了