Location>code7788 >text

Mysql - statement execution plan explained (explain)

Popularity:506 ℃/2024-11-19 08:18:26

summarize

Use explain to output detailed information about the execution of the SELECT statement, including the following information:

  • Table loading order
  • Types of queries in sql
  • What indexes might be used and what indexes are actually used
  • Number of lines read

The Explain execution plan contains the following field information: id, select_type, table, parts, type, possible_keys, key, key_len, ref, rows, filtered, Extra 12 fields.

With explain extended + show warnings, you can provide some additional query optimization information on top of the original explain, and get the possible query statements after optimization (not necessarily the final optimized result).

Test environment:

CREATE TABLE `blog` (
  `blog_id` int NOT NULL AUTO_INCREMENT COMMENT 'Unique blog post id - Primary Key',
  `blog_title` varchar(255) NOT NULL COMMENT 'Title of the blog post', `blog_body` text
  `blog_body` text NOT NULL COMMENT 'The content of the blog post', `blog_time` datetime
  `blog_time` datetime NOT NULL COMMENT 'Blog posting time', `update_time` datetime NOT NULL COMMENT
  `update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  `blog_state` int NOT NULL COMMENT 'blog_state - 0 deleted 1 normal', `user_id` int NOT NULL COMMENT
  `user_id` int NOT NULL COMMENT 'User id',
  PRIMARY KEY (`blog_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8

CREATE TABLE `user` (
  `user_id` int NOT NULL AUTO_INCREMENT COMMENT 'Unique id of the user - primary key',
  `user_name` varchar(30) NOT NULL COMMENT 'User name - cannot be repeated', `user_password` varchar(30) NOT NULL AUTO_INCREMENT COMMENT
  `user_password` varchar(255) NOT NULL COMMENT 'user_password',
  PRIMARY KEY (`user_id`),
  KEY `name` (`user_name`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8

CREATE TABLE `discuss` (
  `discuss_id` int NOT NULL AUTO_INCREMENT COMMENT 'Comment unique id', `discuss_body` int AUTO_INCREMENT COMMENT
  `discuss_body` varchar(255) NOT NULL COMMENT 'Comment content', `discuss_time` int AUTO_INCREMENT COMMENT
  `discuss_time` datetime NOT NULL COMMENT 'Comment time', `user_id` int NOT NULL COMMENT 'comment_time', `user_id` int NOT NULL COMMENT
  `user_id` int NOT NULL COMMENT 'user id', `blog_id` int NOT NULL COMMENT 'comment_time', `blog_id` int NOT NULL COMMENT
  `blog_id` int NOT NULL COMMENT 'blog post id',
  PRIMARY KEY (`discuss_id`)
) ENGINE=InnoDB AUTO_INCREMENT=61 DEFAULT CHARSET=utf8

id

Indicates the order in which select clauses or table operations are performed in a query, the larger the value of id, the higher the priority, the first to be performed.

explain select discuss_body 
from discuss 
where blog_id = (
    select blog_id from blog where user_id = (
        select user_id from user where user_name = 'admin'));

The three tables are nested sequentially and it is found that the innermost subquery with the largest id is executed first.

select_type

Indicates the type of select query, which is mainly used to distinguish various complex queries, such as: common query, union query, subquery, etc.

  • SIMPLE: The simplest select query statement, which does not include subqueries or intersection and difference operations in the query.
  • PRIMARY: The outermost SELECT in the query (the table operation at the outer level of the existent subquery is PRIMARY).
  • SUBQUERY: The first SELECT in the subquery.
  • DERIVED: the driven SELECT subquery (the subquery is in the FROM clause).
  • UNION: UNION is used after SELECT

table

The name of the table for the query, not necessarily the real existing table, has an alias to show the alias, and may also be a temporary table. When there is a subquery in the from clause, the table column is in the format <derivenN>, indicating that the current query relies on the query with id N. The query with id N will be executed first.

partitions

The partition information matched in the query, the value is NULL for non-partitioned tables. when the query is for a partitioned table, parts displays the partitioning of the partitioned table hit.

type

What type the query uses, which is a very important metric in SQL optimization

Access efficiency: const > eq_ref > ref > range > index > ALL

system

When a table has only one row of records (system table), the amount of data is very small, and disk IO is often not required and is very fast. For example, the Mysql system table proxies_priv is loaded in memory when the Mysql service starts, and no disk IO is required to query this table.

const

The query uses a primary key or unique index when operating on a single table.

eq_ref

Primary keys and unique indexes are used as join conditions in multi-table join queries. In the following sql, for each row of the user table (outer loop), there is only one row of the user_role table (inner loop) that satisfies the join condition, and as soon as this row is found, it will jump out of the inner loop and continue to the next round of query in the outer loop.

ref

The lookup condition column uses an index and is not a primary and unique index. Although the index is used, but the value of the indexed column is not unique, so even if the index is used to find the first piece of data, still can not stop, to do a small scan in the vicinity of the target value. But the advantage is that it does not need to sweep the entire table, because the index is ordered, even if there are duplicate values, but also in a very small range to do the scan.

ref_or_null

Similar to ref, it additionally searches for rows containing NULL values

index_merge

The index merge optimization method is used and the query uses more than two indexes. Create a new comment table with id as the primary key and value_id as a non-unique index, execute explain select content from comment where value_id = 1181000 and id > 1000;, the execution result shows that the query uses both id and value_id indexes. The value of the type column is index_merge.

range

Index scans with ranges are preferred over full index scans with indices, which have range restrictions. things like between, and, >, <, in, and or are all range index scans.

index

index includes both select index columns and order by primary key.

order by primary key. In this case, the whole table is scanned for data in the order of the index, and the data you get is sorted by the primary key, so you don't need to do any additional sorting.

Select indexed columns. type is index, and the extra field is using index, also known as the case of index coverage. The data you need to fetch are in the indexed columns, so you don't need to go back to the table to query.

all

Full table scans, where the query does not use indexes, have the worst performance.

possible_keys

The index that may be used in this query. However, this index may not be the index that will be used in the final query.

key

The exact indexes used in this query

ref

The ref column shows which column or constant is used with key to select data rows from the table. Common values are const, func, NULL, and specific field names. When the key column is NULL, that is, when no index is used. If the value is func, the value used is the result of some function.

The execution plan ref for the following SQL is const because a combined index (user_id, blog_id) is used, where user_id = 13 where 13 is constant

mysql> explain select blog_id from user_like where user_id = 13;
+----+-------------+-----------+------------+------+---------------+------+---------+-------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | user_like | NULL       | ref  | ul1,ul2       | ul1  | 4       | const |    2 |   100.00 | Using index |
+----+-------------+-----------+------------+------+---------------+------+---------+-------+------+----------+-------------+

And the following SQL has an execution plan ref value of NULL because the key is NULL and the query does not use an index.

mysql> explain select user_id from user_like where status = 1;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user_like | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    6 |    16.67 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+

rows

Estimating the number of rows that need to be read to find the desired record. Evaluation of SQL performance of a more important data, mysql need to scan the number of rows, very intuitive to show the performance of SQL good or bad, in general, the smaller the value of rows the better!

filtered

The percentage of data returned by the storage engine that, after filtering, leaves the number of records that satisfy the condition

extra

Indicates additional informational notes. For testing purposes, here are two new tables.

CREATE TABLE `t_order` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_id` int DEFAULT NULL,
  `order_id` int DEFAULT NULL,
  `order_status` tinyint DEFAULT NULL,
  `create_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_userid_order_id_createdate` (`user_id`,`order_id`,`create_date`)
) ENGINE=InnoDB AUTO_INCREMENT=99 DEFAULT CHARSET=utf8

CREATE TABLE `t_orderdetail` (
  `id` int NOT NULL AUTO_INCREMENT,
  `order_id` int DEFAULT NULL,
  `product_name` varchar(100) DEFAULT NULL,
  `cnt` int DEFAULT NULL,
  `create_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_orderid_productname` (`order_id`,`product_name`)
) ENGINE=InnoDB AUTO_INCREMENT=152 DEFAULT CHARSET=utf8

using where

Indicates that a WHERE condition was used to filter data during the query. When a query contains a WHERE condition, MySQL filters out the rows that satisfy the condition before proceeding. This process is called "Using Where".

Indicates that the query column is not covered by an index, and the where filter condition is a range of the indexed column's leading columns, or a non-leading column of the indexed column, or a non-indexed column. Filtering the results returned by the storage engine (Post-filter) generally occurs at the MySQL server, not at the storage engine level, so you need to go back to the table to query the data.

using index

The columns of the query are covered by the index, and the where filter condition conforms to the principle of the leftmost prefix, and the index lookup can directly find the data that meets the condition.No need to go back to the tableQuery Data.

Using where&Using index

The queried columns are covered by the index, but the eligible data cannot be found by index lookup, although the eligible data can be found by index scanning, and there is no need to go back to the table to query the data.

Two cases are included (the combined index is (user_id, orde)):

where filter conditions do not match the leftmost prefix principle

The where filter condition is a range of the index column's leading columns

null

The query column is not covered by the index, and the where filter condition is the leading column of the index, that is, the index is used, but some fields are not covered by the index, you must go back to the table to query these fields, NULL in Extra.

using index condition

Index condition pushdown (ICP), first use the where condition to filter the index, after filtering the index to find all the data rows that match the index condition, and then use other conditions in the WHERE clause to filter these data rows.

For the joint index (a, b), in the execution of select * from table where a > 1 and b = 2 statement, only the a field can be used in the index, then in the joint index of the B+Tree to find the first meet the conditions of the primary key value (ID 2), but also need to determine whether the other conditions are met (to see whether b is equal to 2), it is in the joint index to In that case, should we judge it in the union index? Or go back to the primary key index to judge?
MySQL 5.6 introduces the index condition pushdown optimization, which can be used to filter out the records that do not meet the conditions and reduce the number of times you have to return to the table during the traversal process of a union index by judging the fields contained in the union index first.

The case of not using ICP (set optimizer_switch='index_condition_pushdown=off'), as shown below, does not use the where condition to filter the index in step 4:

Use the ICP case (set optimizer_switch='index_condition_pushdown=on'):

The following example uses ICP:

explain select user_id, order_id, order_status from t_order where user_id > 1 and user_id < 5\G;

After turning off ICP (set optimizer_switch='index_condition_pushdown=off'), you can see that extra is listed as using where, and will not use index pushdown.

using temporary

Temporary tables are used to hold intermediate results, commonly in order by and group by. Typically, when group by and order by co-exist and act on different fields, temporary tables are created in order to compute the final result set

filesort

Filesort. Indicates that the index could not be utilized to complete the sort operation, and the following conditions result in filesort:

  • The fields of order by are not indexed fields
  • select Query fields are not all indexed fields
  • The select query fields are all index fields, but the order by fields are not in the same order as the index fields.

using join buffer

Block Nested Loop, which requires a nested loop calculation. This happens when two related tables join and none of the related fields are indexed. For example, both inner and outer types are ALL, and rows are 4. A loop is required for the4*4calculations. A common optimization is to add an index to the associated field to avoid each nested loop calculation.

Interview questions column

Java interview questions columnIt's online, so feel free to visit.

  • If you don't know how to write a resume, resume projects don't know how to package them;
  • If there's something on your resume that you're not sure if you should put on it or not;
  • If there are some comprehensive questions you don't know how to answer;

Then feel free to private message me and I will help you in any way I can.