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.
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
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
Query a table with 6 million data
Undoubtedly appears on the slow query log
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
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;
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
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.
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.
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.
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.
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>.
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.
But at this time we remove the profession in the query conditions, and the joint index becomes invalid.
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.
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.
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
Index failure situation
Index column function operation
When performing an equivalent matching query based on the phone field, the index takes effect.
When performing function operations, the index becomes invalid and a full table scan is performed.
If a numerical operation is performed, the index still takes effect
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.
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
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
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
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
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!
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)
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
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.
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>
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.