MySQL

客户端发出sql –> 连接器校验身份 —> 服务层 —>

  • 语法分析

    • 词法分析和语法分析是两步。词法分析把字符串拆成token
      (识别出SELECT、FROM、WHERE这些关键字),语法分析检查这些token的组合是否符合SQL语法规则, 做这件事的组件叫解析器(Parser)。它最终产出一棵语法树(AST)。
  • 查询缓存

    • 表一次更新缓存全部作废, 写多命中率低, 维护缓存成本大
  • 优化器

    • 优化器评估的是每种执行方案的IO成本和CPU成本。读多少页数据、
      比较多少行,综合算出一个数值,选最小的那个方案。
    • 小表接大表
      • 假设A表10行,B表1000行。
        A驱动B:外层扫10行,每行去B表查一次,查10次。
        B驱动A:外层扫1000行,每行去A表查一次,查1000次。
        如果被驱动表的连接字段上有索引,每次查的代价差不多。那外层循环次数越
        少,总代价越小。
        所以小表驱动大表本质上是在减少外层循环次数。
    • Explain
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
EXPLAIN SELECT * FROM user WHERE name = '张三';

+----+-------------+-------+------+---------------+----------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------+
| 1 | SIMPLE | user | ref | idx_name | idx_name | 102 | const | 3 | NULL |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------+

┌───────────────┬────────────────────────────────────────────────────────────────────────────────────┐
│ 字段 │ 含义 │
├───────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ id │ 查询编号,子查询或UNION时会有多行,id越大越先执行 │
├───────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ select_type │ 查询类型,SIMPLE=简单查询,SUBQUERY=子查询,DERIVED=派生表 │
├───────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ table │ 当前行在访问哪张表 │
├───────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ type │ 访问类型,性能从好到差:const > eq_ref > ref > range > index > ALL │
├───────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ possible_keys │ 这条查询可能用到的索引有哪些 │
├───────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ key │ 优化器最终选了哪个索引,NULL就是没用索引 │
├───────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ key_len │ 用到了索引的多少字节,联合索引时可以判断用了几个字段 │
├───────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ ref │ 索引列跟什么比较,const=常量,字段名=关联查询的连接字段 │
├───────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ rows │ 预估扫描行数,越小越好 │
├───────────────┼────────────────────────────────────────────────────────────────────────────────────┤
│ Extra │ 额外信息,重点关注:Using index(好)、Using filesort(差)、Using temporary(差) │
└───────────────┴────────────────────────────────────────────────────────────────────────────────────┘