preface
- Environment: Mysql 8.0.21
- Explain results vary with the Mysql version
1. The role of Explain?
EXPLAIN statements provide information about how MySQL executes statements. EXPLAIN can be applied to SELECT, DELETE, INSERT, REPLACE, and UPDATE statements
Explain returns one row of information for each table used in the SELECT statement. It lists the output tables in the order they were read by mysql while processing the statement. Mysql uses the nested loop join method to resolve all joins, which means mysql reads a row from the first table, then finds a matching row in the second table, the third table, and so on. After processing all the tables, Mysql outputs the selected columns and backtracks through the list of tables until it finds a table with more matching rows. Read the next row from the table, and proceed to the next table.
Explain Output column information
1.1 id
This is the sequence number of select in the query, and the row can be Null if it references the union result of other rows
The value of the ID column represents the order in which the table is executed. There are three cases:
1.1.1 same id
EXPLAIN SELECT s.*, t.* FROM student s, teacher t
Copy the code
You can see that the explain command isselect
The identifier statement generates a row of information for each table, where the ID is the same, indicating that the two tables are executed from top to bottom, regardless of the order of execution in the SQL.
1.1.2 id different
EXPLAIN SELECT * FROM teacher t WHERE id = ( SELECT s.tid FROM student s WHERE s.id ="2")Copy the code
The two tables with nested subqueries are executed in different order, so explain resolves the query information ID differently. The larger the ID is, the higher the priority is.
1.1.3 Id is the same or different
EXPLAIN SELECT s.id, s.NAME, c.id, c.NAME FROM class c, student s WHERE s.tid = ( SELECT t.id FROM teacher t WHERE t.id = "1")
Copy the code
If the ids are the same, they can be considered as a group and executed from top to bottom in the order shown in the result set (regardless of the order declared in the SQL). A larger ID indicates a higher priority, and the command is executed first.
1.2 select_type
Select the type of all cases as shown in the table below:
1.2.1 SIMPLE
Simple query without any complex queries such as subqueries or union [see example 1.1.1 for details]
1.2.2 PRIMARY
If the query contains any complex subqueries, the outermost layer is marked as primary, commonly known as egg shell. [See example 1.1.2 for details]
1.2.3 the UNION
EXPLAIN SELECT `NAME` FROM tb_employees_china UNION SELECT `NAME` FROM tb_employees_usa
Copy the code
union
After theselect
Is marked asunion
And theunion
In front of theselect
Is marked asprimary
; ifunion
Included in thefrom
Clause, the outer layerselect
Will be marked asderived
1. The UNION RESULT
The result of the merger of two unions. [See example 1.2.3 for details]
1.2.5 DEPENDENT UNION
EXPLAIN SELECT `NAME` FROM tb_employees_china WHERE `NAME` IN ( SELECT `NAME` FROM tb_employees_china UNION SELECT `NAME` FROM tb_employees_usa )
Copy the code
The first condition to satisfy the UNION, and the second or subsequent select in the UNION, depends on external queries.
1.2.6 SUBQUERY
EXPLAIN SELECT * FROM tb_employees_china WHERE id = ( SELECT id FROM tb_employees_china WHERE `name` = "lisi" )
Copy the code
The first select in a subquery is identified as subquery
1.2.7 DEPENDENT SUBQUERY
Select in a subquery that relies on an external query [see example 1.2.4 for details] The first select of this example neutron query is identified as dependent subQuery
1.2.8 DERIVED
Subqueries included in the FROM clause are marked as derived, and mysql recurses these subqueries to put the results in temporary tables (temporary tables are a system burden, but sometimes have to be used).
Note: In this example, the mysql environment is: 5.7
EXPLAIN SELECT * FROM ( SELECT id FROM tb_course tc ) temp
Copy the code
Because Mysql 8.0 is optimized over Mysql 5.7, the above instance will be explained in the 8.0 environment. The subquery will not be identified as derived. No instance of Mysql 8.0 derived has been found. (Follow-up findings will be supplemented)
1.2.9 DEPENDENT DERIVED
Based on Derived, it relies on external queries.
1.2.10 MATERIALIZED
EXPLAIN SELECT * FROM tb_class WHERE `NAME` IN ( SELECT `NAME` FROM tb_class)
Copy the code
The process of saving records in a subquery result set to a temporary table is called Materialize. The temporary table that stores the result set of the subquery is called the materialized table
When the query optimizer executes a statement containing a subquery and chooses to materialize the subquery and then join it with the outer query, the subquery will be identified as MATERIALIZED
The third record of the execution plan has an ID of 2, indicating that this record was executed first and is a single table query. It is identified as MATERIALIZED, and the query optimizer is intended to convert the subquery to MATERIALIZED tables first. The second record of the execution plan is the record whose ID is 1 and table is
. This record is the physical table generated after the execution of the corresponding subquery with ID 2. Then join the tb_class with the physical table (two tables with ID 1).
1.2.11 UNCACHEABLE SUBQUERY
Subqueries whose results cannot be cached must recalculate the results for each row of the external query
1.2.12 UNCACHEABLE UNION
The second or subsequent select in the union is a non-cacheable subquery
Table 1.3
The name of the table referenced by the output row. There are three cases in addition to the table name
-
: union of id values between M and N [see example 1.2.4 for details]
-
: derived table result with id value N [see example 1.2.8 for details]
-
: result of materialized subquery with id value N [see example 1.2.10 for details]
1.4 type
The official full name is Join Type, which means: join type. There are 12 types of type in Mysql 8.0. The following six types are mainly introduced. From top to bottom, efficiency is enhanced, and we should try to optimize our SQL to make it as good a type as possible, taking into account the actual situation.
1.4.1 all (Full Table Scan)
Full scan, a full table scan is performed for each row combination in the table. If the table is the first table that is not marked const, ALL can usually be avoided by indexes that allow rows to be retrieved from the table based on constant or column values from the previous table.
ALL is a violent and primitive search method that is time-consuming and inefficient. But Mysql official describes a few cases where you can use ALL scans:
- The table is so small that performing a table scan is much faster than interrupting a key lookup, which is common for short tables with fewer than 10 rows
- For index columns, there are no restrictions available in the ON or WHERE clauses
- Comparing index columns to constant values
- A low cardinality key (many rows match the key value) is being used through another column, in which case Mysql assumes that multiple key lookups may be required by using keys and that table scans will be faster.
For small tables, table scans are usually appropriate and have a negligible impact on performance, and for large tables, query optimization is a must.
SELECT * FROM `tb_employees_china` WHERE `name` = "zhangsan"
Copy the code
This is because the name column is neither a primary key nor an index, so a full scan is used to find it.
1.4.2 index (Full index Scan)
The difference between index and all is that index scans the index tree and returns data to the table based on the index. Compared with all, they both retrieve data from the full table. In addition, index must read the index first and retrieve data randomly from the table.
SELECT id FROM `tb_employees_usa`
Copy the code
If type is index and Extra is Using index, as shown in the figure above, the overwritten index is used. That is, there is no need to return to the table and the current index tree meets the current query requirements.
1.4.3 range
For example, between… between… between… between… between… between… between… And, <, >, in, or all belong to index range scans.
1.4.4 ref
This join type occurs if the search criteria column uses indexes and does not use primary keys and Unique, that is, ordinary indexes are used instead of primary key indexes and Unique indexes. In this way, even if the first data is quickly found using the index, the scan cannot be stopped. Instead, a small scan near the target value is performed. The advantage is that the entire table does not need to be scanned because the indexes are ordered and even if there are duplicate values, the scan is still a very small range.
Create an index for the name field in tb_employees_USA in the following table and run the following statement:
explain select * from tb_employees_usa where `name` = 'rose'; \Copy the code
1.4.5 eq_ref
What makes eQ_REF so much more interesting than ref is that eQ_REF knows that there is only one result set for this type of lookup, and only one result set if the lookup is using a primary key or a unique index. It is known before the search that there must be only one result set, so the query is stopped immediately the first time a value is found. This type of connection performs a precise query each time and does not require much scanning, so the search is more efficient.
select * from tb_employees_usa join tb_employees_china using(id); \Copy the code
1.4.6 const
In general, if a primary key is placed in the WHERE clause as a query condition, the MySQL optimizer optimizes the query to a constant, i.e., const
select * from tb_employees_usa where `id` = '3'; \Copy the code
1.5 possible_keys
The indexes that the query might use are listed here
1.6 the key
Query the actual index used
1.7 key_len
The smaller the key_len, the better the index. How to calculate the key_len length?
The column type | Whether is empty | The length of the | key_len | note |
---|---|---|---|---|
tinyint | Allow Null | 1 | key_len = 1+1 | Allow NULL and increment the length of key_len by 1 |
tinyint | Do not allow Null | 1 | key_len = 1 | Do not allow NULL |
int | Allow Null | 4 | key_len = 4+1 | Allow NULL and increment the length of key_len by 1 |
int | Do not allow Null | 4 | key_len = 4 | Do not allow NULL |
bigint | Allow Null | 8 | key_len = 8+1 | Allow NULL and increment the length of key_len by 1 |
bigint | Do not allow Null | 8 | key_len = 8 | Do not allow NULL |
char(1) | Allow Null | utf8mb4=4,utf8=3,gbk=2 | key_len = 1*3 + 1 | Allow NULL, character set UTF8, key_len + 1 |
char(1) | Do not allow Null | utf8mb4=4,utf8=3,gbk=2 | key_len = 1*3 | NULL, character set UTf8 not allowed |
varchar(10) | Allow Null | utf8mb4=4,utf8=3,gbk=2 | key_len = 10*3 + 2 + 1 | Dynamic column type, key_len + 2, NULL, key_len + 1 is allowed |
varchar(10) | Do not allow Null | utf8mb4=4,utf8=3,gbk=2 | key_len = 10*3 + 2 | Dynamic column type, key_len length + 2 |
Calculate the length of an index using our execution plan above.
Where, the index name isidx_name
The index type of thevarchar(30)
According to the above chart,varchar(30)
Key_len as follows:30 * 3 + 2 + 1 = 93
Key_len can also be used to determine whether the union index is in effect and which union index is being overridden, as shown in an example.
We will betb_employees_usa
Delete all indexes from the table and create a joint index(name,age)
Execute the following SQL to view the execution plan
explain select * from tb_employees_usa where name='rose';
1Copy the code
- 1
key_len
The value is 93, and the SQL is calculated to use a single index of the federated indexesname
Then run the following SQL to view the execution plan
explain select * from tb_employees_usa where name='rose';
Copy the code
key_len
The value is 98, and the SQL is calculated to use the federated index.
1.8 ref
The value of the ref field is a column or constant, which, along with the value of the key, selects row data from the table. As in the above example
select * from tb_employees_usa join tb_employees_china using(id);
Copy the code
ref
The field values fortest.tb_employees_usa.id
On behalf oftb_employees_usa
的 id
The column withtb_employees_china
To filter the row data with the primary key of
If the condition in the WHERE clause is an equivalent constant, then the ref value is const
1.9 rows
Indicates the number of rows to be scanned during SQL execution. A larger value indicates the number of rows to be scanned and the corresponding time is longer. However, it is important to note that the rows output in EXPLAIN is only an estimate and cannot be fully trusted.
1.10 filtered
Represents the percentage of the data returned by the storage engine that meets the number of queried records after being filtered by the Server layer. This value is a percentage, not a specific number of records.
1.11 Extra
Performance from good to bad:
using index > using where > using temporary > using filesort
Copy the code
using index
: overwrites the index and does not need to return to the tableusing where
: Column data from only usedusing temporary
: indicates that MySQL needs to use temporary tables to store result sets. This is common in sorted and grouped queriesusing filesort
: MySQL cannot use the index to complete the sort operation called “file sort”, generally has this value, it is recommended to use the index to optimizeusing join buffer
: highlights the fact that indexes are not used when fetching join conditions and that connection buffers are needed to store intermediate results. If this value occurs, indexes should be added on a case-by-case basis to improve performancedistinct
: The distInc keyword is used in the select section
summary
This article describes what each field represents in EXPLAIN. For example, if you are interested in MySQL, stay tuned to the MySQL column.