Database Performance Analysis Tool - Execution Plan

   Before I talk about this issue, I will talk about a phenomenon. You may often encounter such a situation and feel that the database is very slow. Why is the database CPU so high, and the memory seems to be insufficient, what should I do? Many students are at a loss, and some A small number of students can talk about such large-scale optimization strategies as index building, separation of reading and writing, and sub-database and sub-table. How to refine it at the execution level? I believe that most of the test students have entered the blind spot. The optimization of the database is a process from qualitative to quantitative, such as whether to query along the index, how many rows have been reduced in scanning, whether the sorting of files has been reduced, how much tps has been improved, etc. Today, we will start from sql itself Analyze the database execution plan for everyone.

  What does database execution plan mean? In my opinion, it is to tell me what this sql needs to do and how it does it. Through the execution plan, we can analyze the performance of sql and improve ideas. We take the mainstream mysql as an example to give you an example of how to make an execution plan;

In mysql, the execution plan can be added with explain before the sql statement, as shown in Figure 1, you have seen that there are many lines,

figure 1

Let me explain the literal meaning line by line

 

Id

Represents the number of the select statement, which is equivalent to the identification function;

Select_type

Query type, such as: simple (without subquery), primary (with subquery or derived query);

Table

the table being queried;

Partitions

Generally check the table partitioning situation;

Type

The query method is an important basis for database performance diagnosis. Generally, there are all, index, ref, eq_ref. This line is the key point. It is very important to remember first!

Possible_keys和key:possible_keys列

Indicates which index MySQL can use to find rows in this table. The following key is the index actually used by MYSQL, which means that the key in possible_keys is in the plan, and the key is actual, that is, there is this index in the plan, which may not be used in actual execution.

Key_len: Displays the key length that MySQL decided to use. If the KEY key is NULL, the length is NULL.
The length of the index used. Shorter lengths are better without loss of accuracy;

row

Indicates that MySQL estimates the number of rows to be read to find the desired record based on table statistics and index selection.

Extra

Contains extra information that doesn't fit in the other columns but is important, remember that this row is also important;

Using index: This value indicates that the corresponding select operation uses a covering index (Covering Index)

MySQL can use the index to return the fields in the select list without having to read the data file again according to the index. An index that contains all the data that meets the query needs is called a covering index

Using where: Indicates that the MySQL server performs "post-filtering" after the storage engine receives the record. If the query fails to use the index, the role of Using where is to remind us that MySQL will use the where clause to filter the result set

Using temporary: Indicates that MySQL needs to use a temporary table to store the result set, which is common in sorting and grouping queries

Using filesort: The sorting operation that cannot be done with indexes in MySQL is called "file sorting"

 

 

 

Next, we will focus on analyzing the type column, which will be explained in combination with the case of the official website. We will display it in order of performance from high to low;

1. system 
This is a special connection type of const. The table has only one row (= system table).

mysql> explain select * from (select * from customer where customer_id=1) a;
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
| id | select_type | table      | type   | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL          | NULL    | NULL    | NULL  |    1 | NULL  |
|  2 | DERIVED     | customer   | const  | PRIMARY       | PRIMARY | 2       | const |    1 | NULL  |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+-------+
2 rows in set

2、const

The table has at most one matching row, which will be read at the start of the query. Since there is only one row, the column values ​​in this row can be considered constant by the rest of the optimizer. const tables are fast because they are only read once! 
const is used when comparing all parts of a PRIMARY KEY or UNIQUE index with a constant value. In the query below, tbl_name can be used for const tables:

SELECT * from tbl_name WHERE primary_key=1;
SELECT * from tbl_name WHERE primary_key_part1=1和 primary_key_part2=2;

3、eq_ref

For each combination of rows from the preceding table, read a row from that table. This is probably the best join type, except for const types. It is used when all parts of an index are joined and the index is a UNIQUE or PRIMARY KEY. 
eq_ref can be used for indexed columns that are compared using the = operator. The comparison value can be a constant or an expression using a column of the table read before the table.
In the following example, MySQL can use eq_ref joins to process ref_tables:

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;
# The difference compared to the following ref is the unique index it uses, that is, the primary key or unique index, while ref uses a non-unique index or a common index. id is the primary key
mysql> explain select a.*,b.* from testa a,testb b where a.id=b.id
;
+----+-------------+-------+--------+---------------+---------+---------+-------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref         | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+-------------+------+-------------+
|  1 | SIMPLE      | b     | ALL    | NULL          | NULL    | NULL    | NULL        |    1 | Using where |
|  1 | SIMPLE      | a     | eq_ref | PRIMARY       | PRIMARY | 4       | sakila.b.id |    1 | NULL        |
+----+-------------+-------+--------+---------------+---------+---------+-------------+------+-------------+
2 rows in set

4、ref

对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。 
ref可以用于使用=或<=>操作符的带索引的列。 
在下面的例子中,MySQL可以使用ref联接来处理ref_tables:

SELECT * FROM ref_table WHERE key_column=expr;
 
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;
# 使用非唯一性索引或者唯一索引的前缀扫描,返回匹配某个单独值的记录行。name有非唯一性索引
mysql> explain select * from testa where name='aaa';
+----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------+
| id | select_type | table | type | possible_keys | key      | key_len | ref   | rows | Extra                 |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------+
|  1 | SIMPLE      | testa | ref  | idx_name      | idx_name | 33      | const |    2 | Using index condition |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-----------------------+
1 row in set
 
mysql> explain select a.*,b.* from testa a,testb b where a.name=b.cname;
+----+-------------+-------+------+---------------+----------+---------+----------------+------+-------------+
| id | select_type | table | type | possible_keys | key      | key_len | ref            | rows | Extra       |
+----+-------------+-------+------+---------------+----------+---------+----------------+------+-------------+
|  1 | SIMPLE      | b     | ALL  | NULL          | NULL     | NULL    | NULL           |    1 | Using where |
|  1 | SIMPLE      | a     | ref  | idx_name      | idx_name | 33      | sakila.b.cname |    1 | NULL        |
+----+-------------+-------+------+---------------+----------+---------+----------------+------+-------------+
2 rows in set

5、 fulltext

Join using a FULLTEXT index.

6、ref_or_null

This join type is like ref, but with the addition that MySQL can specifically search for rows containing NULL values. This join type optimization is often used in solving subqueries.
In the following example, MySQL can use a ref_or_null join to handle ref_tables:

SELECT * FROM ref_table
  WHERE key_column=expr OR key_column IS NULL;
mysql> explain select * from (select cusno from testa t1,testb t2 where t1.id=t2.id) t where cusno =2 or cusno is null;
+----+-------------+------------+-------------+---------------+-------------+---------+--------------+------+--------------------------+
| id | select_type | table      | type        | possible_keys | key         | key_len | ref          | rows | Extra                    |
+----+-------------+------------+-------------+---------------+-------------+---------+--------------+------+--------------------------+
|  1 | PRIMARY     | <derived2> | ref_or_null | <auto_key0>   | <auto_key0> | 5       | const        |    2 | Using where; Using index |
|  2 | DERIVED     | t2         | index       | PRIMARY       | PRIMARY     | 4       | NULL         |    1 | Using index              |
|  2 | DERIVED     | t1         | eq_ref      | PRIMARY       | PRIMARY     | 4       | sakila.t2.id |    1 | NULL                     |
+----+-------------+------------+-------------+---------------+-------------+---------+--------------+------+--------------------------+
3 rows in set

Here, according to the format of the official website, no examples have been tested. If there are examples, please leave a message and I will test and update

7、index_merge

This join type indicates that the index merge optimization method is used. In this case, the key column contains the list of used indexes, and key_len contains the longest key element of the used indexes.

Here, according to the format of the official website, no examples have been tested. If there are examples, please leave a message and I will test and update

8、unique_subquery

unique_subquery is an index lookup function that can completely replace subqueries and is more efficient.
This type replaces ref for IN subqueries of the form:

value IN (SELECT primary_key FROM single_table WHERE some_expr)

Here, according to the format of the official website, no examples have been tested. If there are examples, please leave a message and I will test and update

9、index_subquery

This join type is similar to unique_subquery. IN subqueries can be replaced, but only for non-unique indexes in subqueries of the form:

value IN (SELECT key_column FROM single_table WHERE some_expr)

Here, according to the format of the official website, no examples have been tested. If there are examples, please leave a message and I will test and update

10、range

Retrieve only a given range of rows, using an index to select rows. The key column shows which index was used. key_len contains the longest key element of the index used. In this type the ref column is NULL. 
When using the =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, or IN operators to compare key columns with constants, you can use range

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);

11、index

The index type is the same as the ALL type, except that it scans the index tree in two ways:

If the covering index can satisfy all the data in the query, then only scan the index tree. In this case, Extrathe column is displayed with Using index. It is generally faster to scan only with an index than an ALL scan because the index tree is much smaller than the table data.

A full table scan is used to read data from the index,  Extrathe columns are not displayed Using index.

If the query is only for indexed columns, then MySQL will use this indexindex type

mysql> alter table testa add primary key p_id(id);
Query OK, 0 rows affected
Records: 0  Duplicates: 0  Warnings: 0
 
mysql> create index idx_name on testa(name);
Query OK, 0 rows affected
Records: 0  Duplicates: 0  Warnings: 0
 
mysql> insert into testa values(2,2,'aaa');
Query OK, 1 row affected
 
# Because there is an index on the column name of the query, if this type goes to the index
mysql> explain select name from testa;
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key      | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
|  1 | SIMPLE      | testa | index | NULL          | idx_name | 33      | NULL |    2 | Using index |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
1 row in set
 
# Because the query column cusno is not indexed, or the query column contains a column without index, the query will go through ALL scan, as follows:
mysql> explain select cusno from testa;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | testa | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set
 
# * Contains columns with unseen indexes
mysql> explain select * from testa;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | testa | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set

12、all

For each combination of rows from the previous table, a full table scan is performed. This is usually not good if the table is the first table not marked const, and is usually bad in its case. Often more indexes can be added instead of using ALL so that rows can be retrieved based on constant values ​​or column values ​​in previous tables.

 

Well, the above is what this article wants to say. I hope it will be helpful to you. If there are mistakes, I hope you will point out.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324391684&siteId=291194637