Mysql Advanced-Index (Part 2)

 SQL performance analysis

SQL execution frequency

After the MySQL client successfully connects, server status information can be provided through the show [session|global] status command. Through the following instructions, you can check the access frequency of INSERT, UPDATE, DELETE, and SELECT of the current database.Through the access frequency of sql statements, we can judge whether the current database is mainly based on query or Mainly adding, deleting and modifying, thus providing a reference for database optimization. If it is mainly about additions, deletions and modifications, we can consider not optimizing the index. If it is mainly about query, then you need to consider optimizing the index of the database.

0c62ffe6b8c54f18a43282996117fd77.png

Slow query log 

If the current database isbased on queries, we can view long-consuming queries through the slow query log. Slow query log Records the logs of all SQL statements whose execution time exceeds the specified parameter (long_query_time, unit: seconds, default 10 seconds). MySQL's slow query log is not enabled by default. We can check the system variable slow_query_log.

 Slow query log is turned off by default

375261cd484e4dd887613aa728703c2c.png

 To enable the slow query log, you need to configure the following information in the MySQL configuration file (/etc/my.cnf) and restart the mysql service to make the configuration file take effect.

# Enable MySQL slow log query switch

slow_query_log=1

# Set the slow log time to 2 seconds. If the SQL statement execution time exceeds 2 seconds, it will be regarded as a slow query and the slow query log will be recorded long_query_time=2

ad7047b43a154514a782a5383c7ba976.png

 Query a table with 6 million data

eee2fb613cf440e1812862c6adb66c24.png

 Undoubtedly appears on the slow query loga25b6db262ed4c7fa437a364afaeea05.png

profileinformation

show profiles can help us understand where time is spent when optimizing SQL. Through the have_profiling parameter, you can see whether the current MySQL supports profile operations:

#查询是否有profile参数
select @@have_profiling
#查询profile功能是否开启 0表示关闭 1表示开启
select @@profiling

cc3470d26ce14cf1a04b88efebc140cc.png

 As you can see, MySQL currently supports profile operations, but the switch is turned off. Profiling can be turned on at the session/global level through the set statement:

SET profiling = 1;

 Execute a series of business SQL operations, and then check the execution time of the instructions through the following instructions:

# 查看每一条SQL的耗时基本情况
show profiles;
# 查看指定query_id的SQL语句各个阶段的耗时情况
show profile for query query_id;
# 查看指定query_id的SQL语句CPU的使用情况
show profile cpu for query query_id;

f9c78897baa14e0ba7c47c15a4d63817.png

explain

The EXPLAIN or DESC command obtains information about how MySQL executes the SELECT statement, including how tables are connected and the order in which they are connected during the execution of the SELECT statement. Just add the explain keyword at the beginning of the select statement. By explaining the values ​​of each field, we can analyze whether the SQL statement at this time can go through the index. , is there any situation such as table return query, etc. to facilitate our SQL optimization

7159495b9656426c8f9e8527bcee28f5.png

 Explain the meaning of each field in the execution plan:

Field meaning

id

The sequence number of the select query, indicating the order in which select clauses or table operations are executed in the query.

(id is the same, the execution order is from top to bottom;The ID is different, the larger the value, the earlier it is executed).

select_type

Indicates the type of SELECT. Common values ​​include SIMPLE (simple table, that is, no table connection or subquery is used), PRIMARY (main query, that is, the outer query), UNION (the second or subsequent query statement in UNION) ),

SUBQUERY (subquery included after SELECT/WHERE), etc.

type

indicates the connection type, and the performance ranges from to poor.’s connection types are NULL, system, const, eq_ref, ref, range, index, all.

possible_key

Displays one or more indexes that may be used in this query.

key

The actual index used. If NULL, no index is used.

key_len

indicates the number of bytes used in the index. This value is the maximum possible length of the index field, not the actual length used. Under the premise of not losing accuracy, the shorter the length, the better good.

rows

The number of rows that MySQL considers necessary to execute the query in the innodb engine table is an estimate and may not always be accurate.

filtered

indicates the number of rows returned as a percentage of the number of rows to be read. The larger the value of filtered, the better.

 Index usage

Efficiency verification

Prepare a table with millions of data and query the data based on id. We can find that it only takes 0.01 seconds. This is because id is the primary key index by default. This is a query situation that already has an index.

5cc44a84f8b1404693b2d776819da01a.png

 When querying based on the name field, the index of the name field is not established at this time. You can see that it takes up to 6 seconds.

0767130613884f31a5e4fee757174b84.png

After establishing the index, querying based on name takes only 0.01 seconds. It can be seen that the index can greatly improve query efficiency.

16da7e42c69448ba9c458cdc57346665.png

leftmost prefix rule

If multiple columns are indexed (joint index), the leftmost prefix rule must be followed. The leftmost prefix rule means that the query starts from the leftmost column of the index, and does not skip the Column. If jumps a certain column, the index will be partially invalid (the subsequent field indexes will be invalid).

Taking the tb_user table as an example, there is a joint index idx_user_pro_age_sta. This joint index involves three fields, in order: profession, age, status.

9ee1baad1e4c4c58be19a4f5803f1ac1.png

 The leftmost prefix rule means that when querying, the leftmost changed column, that is, profession, must exist, otherwise all indexes will be invalid. And a column cannot be skipped in the middle, otherwise the field index behind the column will be invalid.

explain select * from tb_user where profession = '软件工程' and age = 31 and status
= '0'

 The three fields of the joint index are bound to take effect in the joint index. As long as the three fields after the where condition are all in the index, it will take effect, regardless of the order of the fields a>. c1a8a66093d84bfc9e34ecf2cfad24b1.png

 We try to gradually reduce the two fields after profession, and we will find that the joint index is still effective, which means that As long as the leftmost field of the index is indexed in the where clause, the index will take effect. . From the figure, we can also infer that the index length of the profession field is 47, the index length of the age field is 2, and the index length of the status field is 5. 0b8902e66d4549c688b83a70ee02f112.png

 But at this time we remove the profession in the query conditions, and the joint index becomes invalid.

a14881ef6dad4f5dac66c0dcb5e1577f.png

 If the leftmost column exists, but the middle column is skipped, then only the index after the middle column will not take effect. Although the joint index is used, the length is only 47, which is the length of the profession field index.

aafcdf3aae264c779169b2cabdab9813.png

 Range query

In the joint index, a range query (>,<) occurs, and the column index on the right side of the range query becomes invalid. It can be seen from the index length that the index of the status field does not take effect.

7621835d4b11437abc299473739e755d.png

 But if we add an equal sign to the range query, that is, ≥ and ≤, the joint index will take effect. If the business allows, use something similar to >= or <=, and avoid using > or < to avoid index failure

f1f5d236c114447e9eaf3942222e9fad.png

 Index failure situation

 Index column function operation

When performing an equivalent matching query based on the phone field, the index takes effect.

56d3207931ac46c18af0f73e8366d7ba.png

 When performing function operations, the index becomes invalid and a full table scan is performed.

f1f6a41b3f9c45d4abd8d93b2ae703df.png

If a numerical operation is performed, the index still takes effect

d3cc25844ead44fe9a3c6eb24bae6965.png

 String without quotes

If you do not add quotation marks to the phone field, the index type will not match and the index will be invalid.

7bc723be16744d31bb30e2c049d5ac6b.png

 Fuzzy query

If there is only a tail fuzzy match, the index will not be invalidated. If it is a header fuzzy match, the index will be invalid.

Head fuzzy query uses full table scan

8b473af81d804d8bbc15ea39e5118ea5.png

 If it is tail fuzzy, then joint index will be used, and the index will take effect. If front and rear fuzzy queries are performed, Since the previous fuzzy query has invalidated the index, the index is also invalid

e15fd297ba7443a58b97516a970bd966.png

 or connection conditions

Conditions separated by or, if the column in the condition before or has an index, but there is no index in the following column, then the indexes involved will not be used,Because the index before or is used, and the column after or does not have an index, a full table scan is still required. The mysql optimizer will decide to directly scan the full table to avoid wasting the time of searching the index tree

Data distribution impact

The same SQL statement, but the incoming field values ​​are different, and the final execution plan is completely different. This is because MySQL will evaluate the efficiency of using indexes and the efficiency of full table scan when querying. If If it is faster to perform a full table scan, then abandon the index and perform a full table scan. Because the index is used to index a small amount of data, if a large amount of data is returned through an index query, it is not as fast as a full table scan, and the index will become invalid. That is,data distribution will also affect whether the index takes effect

3d2c6523c97444b2a71549f0f26084a9.png

 SQL prompt

The sql prompt is to specify the index to be used when executing the query.

 At this point we have a single column index for the profession field

cc3c342851174e1da0aa432f8a380b60.png

 We can see that both the idx_user_pro_age_sta and idx_user_pro indexes in possible_keys may be used. In the end, MySQL chose the idx_user_pro_age_sta index. This is the result of automatic selection by MySQL. What we want to see is a single-column index. After all, I have the final say in my mysql. At this time, I need to use the sql prompt! 38065709f9424d3d924a36153a02c7d1.png

We can add use index (index name) to the select statement to suggest mysql to use the index we specify (it is just a suggestion, mysql will evaluate it again internally)

2b20e99a3ad5489cbc1dbc42320bb1f1.png

 The above use index is just a suggestion. What if mysql doesn't listen? At this time, you needforce index to force mysql to execute the index we specified! Even if the efficiency may decrease, I am happy with it, and I am happy with it even if money cannot buy it. In the picture below, we can see that under normal circumstances, the sta index will not be used. After all, our where clause is checked based on profession, but through our coercion, It can also allow mysql to execute this index

28abba46eb4e4adf85ba09ba7271202e.png

covering index

Try to use covering index and reduce select *. Covering index means that the query uses an index, and all the columns that need to be returned can be found in the index. Using a covering index can reduce or greatly improve queries. The reason is that all the columns that need to be returned have been found in the index columns, and there is no need to return to the table for query. This is also the reason why MySQL preferentially uses joint indexes< /span>

prefix index

introduce

When the field type is a string (varchar, text, longtext, etc.), sometimes a very long string needs to be indexed, which will make the index very large and waste a lot of disk IO during query, affecting query efficiency. At this time, you can only prefix part of the string to create an index, which can greatly save index space and improve indexing efficiency.

 grammar

create index idx_xxxx on table_name(column(n)) ;

Create a prefix index of length 5 for the email field of the tb_user table.

fee7b812272f4be8b8e587bf7ce91875.png

 Prefix length

can be determined based on the selectivity of the index, which refers to the ratio of unique index values ​​(cardinality) to the total number of records in the data table. The higher the index selectivity, the higher the query efficiency. The unique index Selectivity is 1, which is the best index selectivity and has the best performance. That is, it is necessary to ensure that the obtained prefix is ​​as unique as possible and does not repeat.

 Query process

The prefix index is equivalent to the secondary index, but when it matches, must return to the table to query to confirm that the row data is matched according to the prefix index Is the email value of the SQL statement the same as the email value of the SQL statement? At the same time, it is necessary to traverse the next element of the linked list to see if it matches the prefix index. If so, repeat the process just now and return the data. If not, just return the data directly < /span>

88f8c91cfabd49c8a157e95c90721512.png

 Single column index and joint index

 For the covering index mentioned above, MySQL will give priority to using the joint index to reduce table return queries and improve query efficiency.

Single column index: An index contains only a single column.

Union index: An index contains multiple columns.

 Index design principles

1). Create indexes for tables with large amounts of data and frequently queried tables.

2). Create indexes for fields that are often used as query conditions (where), sorting (order by), and grouping (group by) operations.

3). Try to choose columns with high differentiation as indexes, try to build unique indexes, the higher the differentiation, the more efficient the index will be. The higher.

4). If it is a string type field and the field's length is longer, you can adjust the characteristics of the field.. When querying, joint indexes can often cover the index and save storage space. Try to use joint indexes and reduce single-column indexes . 5). Create prefix index.

6). To control the number of indexes, more indexes are not always better. The more indexes, the greater the cost of maintaining the index structure. , will affect the efficiency of additions, deletions, and modifications, and the index will also occupy hard disk space. 

7). If the index column cannot store NULL values, please use NOT NULL to constrain it when creating the table. When the optimizer knows whether each column contains NULL values, it can better determine which index to use most efficiently for the query.

おすすめ

転載: blog.csdn.net/weixin_64133130/article/details/134060684