Mysql Explain analysis

Introducing EXPLAIN

 Let's start with the simplest query:

Query-1
explain select zipcode,firstname,lastname from people;

The EXPLAIN output results have a total of id, select_type, table, type, possible_keys, key, key_len, ref, rows and Extra columns.

id

Query-2
explain select zipcode from (select * from people a) b;

The id is used to sequentially identify the SELECT statement in the entire query. Through the simple nested query above, you can see that the statement with a larger id is executed first. The value may be NULL if this row is used to describe the union result of other rows, such as a UNION statement:

Query-3
explain select * from people where zipcode = 100000 union select * from people where zipcode = 200000;

 

select_type

The types of SELECT statements can be as follows.

SIMPLE

The simplest SELECT query, without using UNION or subqueries. See Query-1.

 

PRIMARY

It is the outermost SELECT statement in a nested query, and the first SELECT statement in a UNION query. See Query-2 and Query-3.

 

UNION

The second and subsequent SELECT statements in the UNION. See Query-3.

 

DERIVED

SELECT statement in the FROM clause of the derived table SELECT statement. See Query-2.

 

UNION RESULT

The result of a UNION query. See Query-3.

 

DEPENDENT UNION

As the name implies, the conditions of UNION and the second and subsequent SELECT statements in UNION need to be met first, and the statement depends on external queries.

Query-4
explain select * from people where id in  (select id from people where zipcode = 100000 union select id from people where zipcode = 200000 );

The select_type of select id from people where zipcode = 200000 in Query-4 is DEPENDENT UNION . You may be surprised that this statement does not depend on the external query ah.

Here, by the way, the MySQL optimizer optimizes the IN operator. The optimizer will optimize the uncorrelated subquery in IN into a correlated subquery (see here for correlated subquery ).

SELECT ... FROM t1 WHERE t1.a IN (SELECT b FROM t2);

A statement like this would be rewritten like this:

SELECT ... FROM t1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.b = t1.a);

So Query-4 is actually rewritten like this:

Query-5
explain select * from people o where exists  (select id from people where zipcode = 100000 and id = o.id union select id from people where zipcode = 200000  and id = o.id);

Digression : Sometimes the MySQL optimizer is too "smart" to cause a great loss in the performance of subqueries whose WHERE conditions include IN(). See section 6.5.1 Correlated Subqueries in High Performance MySQL Third Edition .

 

SUBQUERY

The first SELECT statement in a subquery.

Query-6
explain select * from people  where id =  (select id from people where zipcode = 100000);

 

DEPENDENT SUBQUERY

Same as DEPENDENT UNION vs UNION. See Query-5.

In addition to the above common select_types, there are some others that are not introduced here, and different MySQL versions are not the same.

 

table

Which table is the displayed row of information about. Sometimes it's not really the table name.

Query-7
explain select * from (select * from (select * from people a) b ) c;

You can see the alias displayed if an alias is specified.

<derived N> N is the id value, which refers to the result of the operation corresponding to the id value.

There is also the type <union M,N > , which appears in UNION statements, see Query-4.

Note : MySQL treats these tables as normal tables, but these "temporary tables" do not have any indexes.

 

type

The type column is very important. It is used to describe how the table is associated with the table, and whether an index is used. The term "association" in MySQL is broader than the general sense. MySQL believes that any query is an "association", not just a query that requires two tables to be called an association, so you can also understand how MySQL accesses tables of. There are mainly the following categories.

const

When it is determined that at most one row will match, the MySQL optimizer will read it before the query and only once, so it is very fast. const is only used when comparing constants to primary keys or unique indexes, and to compare all indexed fields. The people table has a primary key index on id and a secondary index on (zipcode, firstname, lastname). So Query-8's type is const and Query-9 is not:

Query-8
explain select * from people where id=1;

Query-9
explain select * from people where zipcode = 100000;

Note that the following Query-10 cannot use const table, although it is also the primary key, it will only return one result.

Query-10
explain select * from people where id >2;

 

system

This is a special case of the const join type, where only one row of the table satisfies the condition.

Query-11
explain select * from (select * from people where id = 1 )b;

<derived2> is already a const table and has only one record.

 

eq_ref

The eq_ref type is the best join type except const, which is used when all parts of an index are joined and the index is UNIQUE or PRIMARY KEY.

Note that the InnoDB and MyISAM engines are a bit different at this point. InnoDB type will be All when the amount of data is relatively small. The people and people_car we created above are InnoDB tables by default.

Query-12
explain select * from people a,people_car b where a.id = b.people_id;

Let's try to create two MyISAM tables people2 and people_car2:

copy code

CREATE TABLE people2(
    id bigint auto_increment primary key,
    zipcode char(32) not null default '',
    address varchar(128) not null default '',
    lastname char(64) not null default '',
    firstname char(64) not null default '',
    birthdate char(10) not null default ''
)ENGINE = MyISAM;

CREATE TABLE people_car2(
    people_id bigint,
    plate_number varchar(16) not null default '',
    engine_number varchar(16) not null default '',
    lasttime timestamp
)ENGINE = MyISAM;

copy code

Query-13
explain select * from people2 a,people_car2 b where a.id = b.people_id;

I guess this is a result of InnoDB's performance trade-off.

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. If the index used by the association happens to be the primary key again, then it becomes a better const:

Query-14
explain select * from people2 a,people_car2 b where a.id = b.people_id and b.people_id = 1;

 

ref

This type differs from eq_ref in that it is used in association operations that only use the leftmost prefix of the index, or the index is not UNIQUE and PRIMARY KEY. ref can be used on indexed columns using the = or <=> operators.

To illustrate that we recreate the people2 and people_car2 tables above, still using MyISAM but not specifying the primary key for the id. Then we create non-unique indexes for id and people_id respectively.

reate index people_id on people2(id);
create index people_id on people_car2(people_id);

Then execute the following query:

Query-15
explain select * from people2 a,people_car2 b where a.id = b.people_id and a.id > 2;

Query-16
explain select * from people2 a,people_car2 b where a.id = b.people_id and a.id = 2;

Query-17
explain select * from people2 a,people_car2 b where a.id = b.people_id;

Query-18
explain select * from people2 where id = 1;

Looking at the above Query-15, Query-16 and Query-17, Query-18, we find that MyISAM also has different strategies for processing ref types.

For the ref type, the results of executing the above three statements on InnoDB are exactly the same.

 

fulltext

Linking is done using full-text indexing. Generally, the indexes we use are B-trees, so there is no example here.

 

ref_or_null

This type is similar to ref. But MySQL will do an extra search for columns that contain NULL. This join type optimization is often used in solving subqueries. (see here for details ).

Query-19
mysql> explain select * from people2 where id = 2 or id is null;

Query-20
explain select * from people2 where id = 2 or id is not null;

Note that Query-20 does not use ref_or_null, and InnnoDB behaves differently this time (to be verified in the case of a large amount of data).

 

index_merger

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. See here for index merge optimization .

 

unique_subquery

This type replaces ref for IN subqueries of the form:

value IN (SELECT primary_key FROM single_table WHERE some_expr)

unique_subquery is an index lookup function that can completely replace subqueries and is more efficient.

 

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)

 

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 comparing key columns with constants using the =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, or IN operators, you can use range:

Query-21
explain select * from people where id = 1 or id = 2;

Note in my tests: found that type is range only if id is a primary key or unique index.

By the way, MySQL uses the same range to represent range queries and list queries.

explain select * from people where id >1;

explain select * from people where id in (1,2);

But in fact there is a big difference in how MySQL uses indexes in the two cases:

We're not being picky: the two access efficiencies are different. For range conditional queries, MySQL cannot use other index columns after the range column, but there is no such restriction for "multiple equal value conditional queries".

- From "High Performance MySQL Third Edition"

 

index

The join type is the same as ALL, except that only the index tree is scanned. This is usually faster than ALL because index files are usually smaller than data files. This type is usually used to tell us whether the query uses the index for sorting operations.

Query-22
explain select * from people order by id;

As for under what circumstances MySQL will use the index for sorting, we will study it carefully when there is time. The most typical is the order by followed by the primary key.

 

ALL

The slowest way is a full table scan.

 

In general: the performance of the above connection types decreases in sequence (system>const), and different MySQL versions, different storage engines and even different data volumes may perform differently.

 

possible_keys

The possible_keys column indicates which index MySQL can use to find rows in this table.

 

key

The key column shows the key (index) that MySQL actually decided to use. If no index is selected, the key is NULL. To force MySQL to use or ignore indexes on the possible_keys column, use FORCE INDEX, USE INDEX, or IGNORE INDEX in the query.

 

key_len

The key_len column shows the key length that MySQL decided to use. If the key is NULL, the length is NULL. The length of the index used. Shorter lengths are better without loss of accuracy.

 

ref

The ref column shows which column or constant is used along with key to select rows from the table.

 

rows

The rows column shows the number of rows that MySQL thinks it must examine when executing the query. Note that this is an estimate.

 

Extra

Extra is another very important column in the EXPLAIN output. This column displays some detailed information of MySQL during the query process. It contains a lot of information. Only a few key points are introduced.

Using filesort 

MySQL has two ways to generate ordered results, through sorting operations or using indexes. When Using filesort appears in Extra, it means that MySQL uses the latter, but note that although it is called filesort, it does not mean that files are used for sorting. Sorting is done in memory whenever possible. In most cases, it is faster to use the index to sort, so generally consider optimizing the query at this time.

 

Using temporary

It means that a temporary table is used. Generally speaking, it means that the query needs to be optimized. Even if the use of temporary table cannot be avoided, the use of hard disk temporary table should be avoided as much as possible.

 

Not exists

MYSQL optimizes LEFT JOIN, once it finds a row that matches the LEFT JOIN criteria, it doesn't search anymore.

 

Using index 

Indicates that the query is covering the index, which is a good thing. MySQL filters unwanted records directly from the index and returns the hits. This is done by the MySQL service layer, but there is no need to go back to the table to query records.

 

Using index condition

This is a new feature in MySQL 5.6 called "index condition push". To put it simply, MySQL used to be unable to perform operations such as like on indexes, but now it can, which reduces unnecessary IO operations, but can only be used on secondary indexes, click here for details .

 

Using where

A WHERE clause is used to restrict which rows will be matched to the next table or returned to the user.

Note : Using where appears in the Extra column, indicating that the MySQL server returns the storage engine to the service layer and then applies the WHERE condition filter.

 

The output content of EXPLAIN is basically introduced. It also has an extended command called EXPLAIN EXTENDED, which is mainly used in conjunction with the SHOW WARNINGS command to see some more information. One of the more useful ones is to see the SQL refactored by the MySQL optimizer.

 

Ok, EXPLAIN understands here, in fact, these contents are available on the Internet, but they will be more impressed by their actual practice. The next section will introduce SHOW PROFILE, slow query logs, and some third-party tools.

Guess you like

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