Mysql优化

Explain执行计划

Explain是Mysql的优化神器,它可以对一条Query SQL进行分析, 并输出SQL的详细信息,以便于优化SQL。

下面是Explain解析一条SELECT的例子:

Explain执行计划

EXPLAIN输出的属性如下:

  • id: id是SELECT查询的序列号,表示一条SELECT或SELECT中子查询的执行顺序。主要有2种情况:

    • 如果id相同,可以被认为是同一分组,执行顺序,从上到下。
    • 如果id不同,id值越大,那么越先执行。
  • select_type: select_type是为了区分简单查询,复杂查询,子查询等查询类型。 select_type主要有如下值:

    • SIMPLE: SIMPLE代表简单查询,SELECT中不包含子查询或联合查询等复杂查询。

    • SUBQUERY: SUBQUERY表示子查询部分。

    • PRIMARY: PRIMARY表示最外层查询,如果一个SELECT中包含子查询,

           那么最外层的查询就是PRIMARY。
      
    • DERIVED: DERIVED代表查询的结果被放入临时表中。

           如FROM 语句后跟着一个 SELECT ,那么SELECT的结果就可能被放入临时表中。
      
    • UNION: UNION代表联合查询,也就是UNION后的SELECT。

    • UNION RESULT: UNION RESULT代表联合查询的结果。

  • table: table表示查询的表。

  • partitions: partition代表查询匹配的分区,对于非分区表为NULL。

  • type: 查询类型,是衡量SQL的一个重要的指标。

      一般来说,至少要达到range标准,最好达到ref。
      它有如下值:
    
    • SYSTEM: SYSTEM代表表只有一条记录,他是CONST类型的一个特例。

    • CONST: CONST表示表只最多只有一个匹配行,只用读一次,

         因此优化器可以视查询结果为一个常量。
      
    • EQ_REF: EQ_REF代表唯一性索引扫描。比如以 unique key索引或主键作为条件,

          这2种索引都是唯一的,表中只有一条记录与之匹配。
      
    • REF: REF代表非唯一索引匹配,返回匹配条件的所有行。

       比如WHERE条件的列有索引,经过匹配后,发现有多条符合条件的记录。
      
    • RANGE: RANGE表示范围扫描。如使用>,<,BETWWEN等条件。

    • INDEX: INDEX代表全表扫描,不过它与ALL的区别在于,

         INDEX是在索引列上进行全表扫描,一般要比ALL快。
      
    • ALL: ALL代表全表扫描,效率最低。

  • possible_keys: poosible keys代表查询涉及到的字段如果有索引会被列出来,

               但不一定使用。
    
  • key: key代表查询实际使用到的索引,如果为NULL,则没有使用索引。

  • key_len: key_len表示使用索引的实际长度。

  • ref: ref表示与索引比较的列或这常量。

     假设 WHERE以主键作为条件 id = 10,那么ref显示的就是const,
     因为主键为10,就是一个常量。
    
  • rows: rows代表查询优化器估算查询结果集要扫描的行数,

      也就是执行SELECT预计需要扫描的行数。
    
  • filtered: filtered代表SELECT执行时过滤掉的记录与rows的百分比。

          filtered 显示的百分比 与 rows 的乘积就是查询时过滤掉的行数。
    
  • EXTRA: 显示SQL执行时的附加信息

开启慢查询日志

慢查询用于记录查询超过某个临界值的SQL。

使用:

SHOW VARIABLES LIKE 'SLOW_QUERY_LOG';

查看慢查询是否开启,如果显示OFF,那么执行:

set GLOBAL SLOW_QUERY_LOG = on

开启慢查询日志。


使用:

SHOW VARIABLES LIKE 'LONG_QUERY_TIME';

查看慢查询临界值,单位: 秒。

使用:

SET LONG_QUERY_TIME=2

设置慢查询临界值。

开启慢查询后,会在mysql的数据目录下产生xxx-slow.log慢查询日志文件, 一旦某条SQL超过了临界值,就会被记录到慢查询日志文件中。

为什么要求字段尽量设置为NOT NULL?

因为Mysql难以优化可以为空的字段,一旦字段被建立了索引, 那么就需要额外的空间来存储此当前行记录是否为NULL的标识。

为什么主键尽量设置成有序和整型?

这个问题其实在索引章节就说过了,索引的结构是B+树,B+树最大的优点就是顺序查找, 有序的主键当然有利于查找,像UUID等这种长字符串,连排序都难以解决。

results matching ""

    No results matching ""