zoukankan      html  css  js  c++  java
  • mysql EXPLAIN Join Types 手册解释 及数据实操

     第一部分:名称解释

    文档地址

    https://dev.mysql.com/doc/refman/5.7/en/explain-output.html

    EXPLAIN Join Types:

    The type column of EXPLAIN output describes how tables are joined. In JSON-formatted output, 
    these are found as values of the access_type property. The following list describes the join types,
    ordered from the best type to the worst:

    Explains 列描述了表与表之间是如何连接的,在JSON格式的输出中,这些被发现为access_type属性的值。下面对于join 的不同类型描述列表中,分布从最好到最坏

    system

    The table has only one row (= system table). This is a special case of the const join type.
    表中只有一列数据,是const 连接类型中的一个特殊列子

    const

    The table has at most one matching row, which is read at the start of the query. Because there is only one row, 
    values from the column in this row can be regarded as constants by the rest of the optimizer. const tables are
    very fast because they are read only once.

    表中至多有一条可以被匹配到,在查询最开始的时候会被读取。由于只有一条数据,因此该行中的列值会被剩下的优化器认定为常量值。常量值由于只需
    要读取一次,因此被认为是非常快速的。
    const is used when you compare all parts of a PRIMARY KEY or UNIQUE index to constant values. In the following queries, 
    tbl_name can be used as a const table:

    const 类型被使用的条件是 当你把主键或者唯一索引作为一个整体和常量做对比
    SELECT * FROM tbl_name WHERE primary_key=1;
    
    SELECT * FROM tbl_name
      WHERE primary_key_part1=1 AND primary_key_part2=2;

    eq_ref

    One row is read from this table for each combination of rows from the previous tables. Other than the system and const 
    types, this is the best possible join type. It is used when all parts of an index are used by the join and the index is
    a PRIMARY KEY or UNIQUE NOT NULL index.
    当前面的表join到当前表的时候,每一个join 当前表只会有一条记录被连接到。除了system和const类型,这是最好的连接类型。当索引整体被使用到并且索引
    是主键或者唯一索引的时候,会出现这种类型的连接
    eq_ref can be used for indexed columns that are compared using the = operator. The comparison value can be a constant or 
    an expression that uses columns from tables that are read before this table. In the following examples, MySQL can use an eq_ref
    join to process ref_table:
    当比较是等于号的时候,eq_ref 可以被索引使用到。比较可以是一个常量或者是一个表达式,该表达式是另外一个连接表中的一列。
    SELECT * FROM ref_table,other_table
      WHERE ref_table.key_column=other_table.column;
    
    SELECT * FROM ref_table,other_table
      WHERE ref_table.key_column_part1=other_table.column
      AND ref_table.key_column_part2=1;

    ref

    All rows with matching index values are read from this table for each combination of rows from the previous tables. 
    ref is used if the join uses only a leftmost prefix of the key or if the key is not a PRIMARY KEY or UNIQUE index
    (in other words, if the join cannot select a single row based on the key value). If the key that is used matches only
    a few rows, this is a good join type.
    所有具有匹配索引值的行都从这个表中读取,用于以前表中的每个行的组合。 如果连接仅使用键的最左边的前缀,或者键不是PRIMARY KEY或UNIQUE索引(换句话说,
    如果连接不能根据键值选择单个行),则使用ref。如果使用的键只匹配几行,这是一个很好的连接类型。
    SELECT*FROMref_tableWHEREkey_column=expr;SELECT*FROMref_table,other_tableWHEREref_table.key_column=other_table.column;SELECT*FROMref_table,other_tableWHEREref_table.key_column_part1=other_table.columnANDref_table.key_column_part2=1;

    ref_or_null

    This join type is like ref, but with the addition that MySQL does an extra search for rows that contain NULL values. This join 
    type optimization is used most often in resolving subqueries. In the following examples, MySQL can use a ref_or_null join to process ref_table:
    这种连接类型与ref类似,但是除此之外,MySQL还对包含NULL值的行进行额外的搜索。 这种连接类型优化最常用于解析子查询。 在以下示例中,MySQL可以使用ref_or_null连接来处理ref_table:
    SELECT * FROM ref_table
      WHERE key_column=expr OR key_column IS NULL;

    unique_subquery

    This type replaces eq_ref for some IN subqueries of the following form,is just an index lookup function that replaces the subquery completely 
    for better efficiency.
    这种类型替换了以下形式的一些IN子查询的eq_ref,只是一个索引查找函数,它可以完全替代子查询以提高效率。
    value IN (SELECT primary_key FROM single_table WHERE some_expr)

    range

    Only rows that are in a given range are retrieved, using an index to select the rows. The key column in the output row indicates which 
    index is used. The key_len contains the longest key part that was used. The ref column is NULL for this type. range can be used when a key column is compared to a constant using any of the =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, or IN() operators:
    只有在给定范围内的行才能被检索,使用索引来选择行。 输出行中的key column指示哪一个索引被使用。 key_len包含使用的最长key部分。 这个类型的ref列是NULL。
    SELECT * FROM tbl_name
      WHERE key_column = 10;
    
    SELECT * FROM tbl_name
      WHERE key_column BETWEEN 10 and 20;
    
    SELECT * FROM tbl_name
      WHERE key_column IN (10,20,30);
    
    SELECT * FROM tbl_name
      WHERE key_part1 = 10 AND key_part2 IN (10,20,30);

    index

    The index join type is the same as ALL, except that the index tree is scanned. This occurs two ways:
    If the index is a covering index for the queries and can be used to satisfy all data required from the table,
    only the index tree is scanned. In this case, the Extra column says Using index. An index-only scan usually is
    faster than ALL because the size of the index usually is smaller than the table data.
    A
    full table scan is performed using reads from the index to look up data rows in index order. Uses index does not
    appear in the Extra column. MySQL can use this join type when the query uses only columns that are part of a single index.
    索引连接类型与ALL相同,只是索引树被扫描。 这发生在两个方面:
    
    如果索引是查询的覆盖索引,并且可用于满足表中所需的所有数据,则只扫描索引树。 在这种情况下,额外列说使用索引。 仅索引扫描通常比ALL快,因为索引的大小通常小于表数据。
    
    全表扫描使用索引中的读取来按索引顺序查找数据行。 使用索引不会出现在Extra列中。
    
    当查询只使用属于单个索引一部分的列时,MySQL可以使用这种连接类型。

    第二部分:数据演示

    Server version: 10.0.24-MariaDB-7 Ubuntu 16.04

    1.查看表数据类型

    MariaDB [member]> show create table test;
    
    | test  | CREATE TABLE `test` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `member_id` int(11) NOT NULL,
      `price` decimal(10,2) NOT NULL,
      `brand` varchar(100) NOT NULL,
      `consume_time` date DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `price` (`price`),
      KEY `member_id` (`member_id`),
      KEY `member_price` (`member_id`,`price`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 |

    有一个主键ID 两个普通索引 还有一个联合索引

    2.查看数据大小

    MariaDB [member]> select count(*) from test;
    +----------+
    | count(*) |
    +----------+
    |   597383 |
    +----------+

    3.主键 Using index 演示

    MariaDB [member]> explain SELECT id from test where id = 100;
    +------+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
    | id   | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra       |
    +------+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
    |    1 | SIMPLE      | test  | const | PRIMARY       | PRIMARY | 4       | const |    1 | Using index |
    +------+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
    MariaDB [member]> explain SELECT * from test where id = 100;
    +------+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
    | id   | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra |
    +------+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
    |    1 | SIMPLE      | test  | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
    +------+-------------+-------+-------+---------------+---------+---------+-------+------+-------+

    type是const类型 如果是只筛选ID列 则Extra会显示Using index 说明只需要遍历索引就可以获取需要的数据

    4.辅助索引 Using index 演示

    MariaDB [member]> explain SELECT price from test where price=1;
    +------+-------------+-------+------+---------------+-------+---------+-------+------+-------------+
    | id   | select_type | table | type | possible_keys | key   | key_len | ref   | rows | Extra       |
    +------+-------------+-------+------+---------------+-------+---------+-------+------+-------------+
    |    1 | SIMPLE      | test  | ref  | price         | price | 5       | const | 1874 | Using index |
    +------+-------------+-------+------+---------------+-------+---------+-------+------+-------------+

    type是ref格式的 用到了键 price 由于只需要筛选索引列 索引 提示信息是Using index

    MariaDB [member]> explain SELECT price from test where price<100;
    +------+-------------+-------+-------+---------------+-------+---------+------+--------+--------------------------+
    | id   | select_type | table | type  | possible_keys | key   | key_len | ref  | rows   | Extra                    |
    +------+-------------+-------+-------+---------------+-------+---------+------+--------+--------------------------+
    |    1 | SIMPLE      | test  | range | price         | price | 5       | NULL | 117580 | Using where; Using index |
    +------+-------------+-------+-------+---------------+-------+---------+------+--------+--------------------------+

    这里type是range, key是price 说明用到了索引。提示信息Using where ,Using index 。由于只需要price 所以遍历索引列即可得到数据 ,后面mysql会再根据where条件筛选

    5.Using index condition 演示

    MariaDB [member]> explain SELECT * from test where member_id<10;
    +------+-------------+-------+-------+------------------------+-----------+---------+------+------+-----------------------+
    | id   | select_type | table | type  | possible_keys          | key       | key_len | ref  | rows | Extra                 |
    +------+-------------+-------+-------+------------------------+-----------+---------+------+------+-----------------------+
    |    1 | SIMPLE      | test  | range | member_id,member_price | member_id | 4       | NULL |   62 | Using index condition |
    +------+-------------+-------+-------+------------------------+-----------+---------+------+------+-----------------------+
    

    type 是range 可以看到提示信息是 Using index condition

    MariaDB [member]> explain SELECT * from test where price>10;
    +------+-------------+-------+------+---------------+------+---------+------+--------+-------------+
    | id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
    +------+-------------+-------+------+---------------+------+---------+------+--------+-------------+
    |    1 | SIMPLE      | test  | ALL  | price         | NULL | NULL    | NULL | 595835 | Using where |
    +------+-------------+-------+------+---------------+------+---------+------+--------+-------------+
    

    type是all 可以看到 key 列是NULL 且提示信息只有 Using where。与上面的策略不同 我的理解是 这里mysql判断需要的遍历的数据比较多  没有走索引  这样更快 因为回查主索引 也比较耗时耗力 

  • 相关阅读:
    (原创) mac 10.9.2 eclipse 的 CDT 的 异常的修复
    (转) Virtual function
    (转) ROS NAMING AND NAMESPACES
    (转) Data structures
    (转) Dynamic memory
    java string类
    eclipse 的快捷键
    java抽象类和接口
    面向对象的三大特征
    Java 中的多态
  • 原文地址:https://www.cnblogs.com/alin-qu/p/7896103.html
Copyright © 2011-2022 走看看