MySQL 查询优化

把查询看作一系列子任务,优化方式:消除一些子任务,减少子任务执行次数,子任务运行得更快。
响应时间当作重要标准。

查询的生命周期(大概):从客户端到服务器,服务器解析,生成执行计划并返回结果给客户端。
查询花费时间在网络,CPU计算,生成统计信息和执行计划,锁等待(互斥等待),底层存储引擎的调用(上下文切换和系统调用),IO操作

6.2.1 请求不需要的数据:
1.查询不需要的记录:扫描行数远远大于返回行数。
2.多表关联时返回全部列
3.总是取出全部列:select * 总是不太好
4.重复查询相同的数据,可以建立缓存

6.2.2
MySQL最简单的衡量查询开销的三个指标:这三个指标都会记录在MySQL慢日志
1.响应时间=服务时间+排队时间(等待IO、等待行锁)
2.扫描行数
3.返回行数

EXPLAIN语句的type列反映了访问类型(查询访问方式怎么返回结果)
EXPALIN内容详解

/*mysql 8.0 database sakila*/
mysql> select * from film_actor where film_id =1;
+----------+---------+---------------------+
| actor_id | film_id | last_update         |
+----------+---------+---------------------+
|        1 |       1 | 2006-02-15 05:05:03 |
|       10 |       1 | 2006-02-15 05:05:03 |
|       20 |       1 | 2006-02-15 05:05:03 |
|       30 |       1 | 2006-02-15 05:05:03 |
|       40 |       1 | 2006-02-15 05:05:03 |
|       53 |       1 | 2006-02-15 05:05:03 |
|      108 |       1 | 2006-02-15 05:05:03 |
|      162 |       1 | 2006-02-15 05:05:03 |
|      188 |       1 | 2006-02-15 05:05:03 |
|      198 |       1 | 2006-02-15 05:05:03 |
+----------+---------+---------------------+
10 rows in set (0.06 sec)

mysql> explain select * from film_actor where film_id =1;
+----+-------------+------------+------------+------+----------------+----------------+---------+-------+------+----------+-------+
| id | select_type | table      | partitions | type | possible_keys  | key            | key_len | ref   | rows | filtered | Extra |
+----+-------------+------------+------------+------+----------------+----------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | film_actor | NULL       | ref  | idx_fk_film_id | idx_fk_film_id | 2       | const |   10 |   100.00 | NULL  |
+----+-------------+------------+------------+------+----------------+----------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from film_actor where film_id =1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: film_actor
   partitions: NULL
         type: ref
possible_keys: idx_fk_film_id
          key: idx_fk_film_id
      key_len: 2
          ref: const
         rows: 10
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.00 sec)

删除外键 fk_film_actor_film和索引 idx_fk_film_id

         type: ALL
         rows: 5073
        Extra: Using where

访问类型:全表扫描ALL
Extra: Using where表示通过where条件来筛选存储引擎返回的记录.

应用WHERE条件的三种方式,从好到坏:
1.在索引中使用where,存储引擎层。
2.使用索引覆盖扫描(Extra: Using index),MySQL服务器层,无须回表查询记录。
3.Extra: Using where,MySQL服务器层,从数据表读出数据再过滤。

使用索引减少扫描行数
mysql> select actor_id,count(*) from film_actor group by actor_id;
+----------+----------+
| actor_id | count(*) |
+----------+----------+
|        1 |       19 |
|        2 |       25 |
|        3 |       22 |
|      ... |     ...  | 
200 rows in set (0.01 sec)

如果发现查询需要扫描大量的数据但只返回少量行的优化:
1.使用索引覆盖扫描
2.改变库表结构
3.重写复杂的查询

6.7 优化特定类型的查询
6.7.1 count()
1.统计某列的数量,不统计NULL。count(colmun)
2.统计行数,统计NULL。count(*),count(1)

一般查询时,count(1)比count(*)快;
但主键作为count的参数时,count(主键)比count(1)和count(*)都快;
MyISAM 的 count() p237。

你可能感兴趣的:(MySQL 查询优化)