SQL optimization steps
In the application development process, due to the small amount of initial data, developers pay more attention to achieve the function to write SQL statements, but when the application formally launched, with the rapid growth of production volume data, many SQL statements began to reveal the performance issues, the impact on production is also growing, then these problematic SQL statements can become a bottleneck in overall system performance, so we have to optimize them, this chapter describes in detail optimizing SQL statements in MySQL method.
When faced with a SQL database performance problems, we should be where to start to carry out a systematic analysis, makes it possible to locate the problem as soon as possible and solve the problem as soon as possible SQL.
1.1 View SQL execution frequency
After the MySQL client connection is successful, the show [session | global] status command provides server status information. show [session | global] status can add parameters "session" or "global" to display the results of session-level meter (current connection) and global level statistics (from the database since the last start) as needed. If you do not write, the default parameter is "session".
The following command displays the current session of the values of all statistical parameters:
show status like 'Com_______';
result:
show status like 'Innodb_rows_%';
Com_xxx xxx represents the number of times each statement was executed, we usually are more concerned about several statistical parameters.
parameter | meaning |
---|---|
Com_select | The number of executions select operation, a query is only incremented by one. |
Com_insert | INSERT operation is performed the number of times, for bulk inserts INSERT operations, accumulating only once. |
Com_update | UPDATE number of operations performed. |
Com_delete | DELETE number of operations performed. |
Innodb_rows_read | select query number of rows returned. |
Innodb_rows_inserted | Perform several rows of inserts INSERT operations. |
Innodb_rows_updated | The number of rows UPDATE operations perform updates. |
Innodb_rows_deleted | The number of rows DELETE operation executed deleted. |
Connections | The number of attempts to connect to the MySQL server. |
Uptime | Server working hours. |
Slow_queries | The number of slow queries. |
Com _ ***: These parameters are cumulative operating table for all storage engines.
Innodb _ ***: these parameters only for the InnoDB storage engine, accumulated algorithm is slightly different.
1.2 Positioning inefficient SQL execution
It can be positioned lower efficiency in the implementation of SQL statements in two ways.
- Slow query log: locate those lower efficiency in the implementation of SQL statements by the slow query log, with -log-slow-queries [= file_name] option to start, mysqld write execution time exceeds that contains all the SQL statements long_query_time seconds log file.
- show processlist: Slow query log records only after the end of the query, so when there is a problem in the application reflect the efficiency of the query and slow query log can not locate the problem, you can use the show processlist command to view the current thread MySQL in progress, including the state of the thread, whether lock tables, etc., can be viewed in real-time implementation of SQL, as well as some table lock to optimize the operation.
SHOW PROCESSLIST;
result:
1) id列,用户登录mysql时,系统分配的"connection_id",可以使用函数connection_id()查看
2) user列,显示当前用户。如果不是root,这个命令就只显示用户权限范围的sql语句
3) host列,显示这个语句是从哪个ip的哪个端口上发的,可以用来跟踪出现问题语句的用户
4) db列,显示这个进程目前连接的是哪个数据库
5) command列,显示当前连接的执行的命令,一般取值为休眠(sleep),查询(query),连接(connect)等
6) time列,显示这个状态持续的时间,单位是秒
7) state列,显示使用当前连接的sql语句的状态,很重要的列。state描述的是语句执行中的某一个状态。
一个sql语句,以查询为例,可能需要经过copying to tmp table、sorting result、sending data等状态才可以完成
8) info列,显示这个sql语句,是判断问题语句的一个重要依据
1.3 explain analysis of the implementation plan
After the query to inefficient SQL statements through the above steps, you can get information on how MySQL SELECT statement execution, including the order of how to connect and connection in the course of a SELECT statement executed by EXPLAIN tables or DESC command.
Query execution plans for SQL statements:
EXPLAIN SELECT * FROM city WHERE city_id = '1';
result:
EXPLAIN SELECT * FROM city WHERE country_id = '1';
Field | meaning |
---|---|
id | SEQ ID NO select query is a set of numbers indicating the order of clauses or select a query execution operation table. |
select_type | SELECT indicates the type of common values have the SIMPLE (simple table, i.e., without the use of tables or subquery is connected), a PRIMARY (main query, i.e., the outer query), UNION (second or later query the UNION ), the first SELECT sUBQUERY (sub-query), etc. |
table | Table output result set |
type | A table of connection types, the performance from good to poor as connection type (system -> const -----> eq_ref ------> ref -------> ref_or_null ----> index_merge -> index_subquery -----> range -----> index ------> all) |
possible_keys | When it indicates that the query, the index might be used |
key | It indicates the index of actual use |
key_len | Length of the index field |
rows | The number of scanning lines |
extra | And described implementation |
### 1.3.1 Environmental ready
CREATE TABLE `t_role` (
`id` varchar(32) NOT NULL,
`role_name` varchar(255) DEFAULT NULL,
`role_code` varchar(255) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_role_name` (`role_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `t_user` (
`id` varchar(32) NOT NULL,
`username` varchar(45) NOT NULL,
`password` varchar(96) NOT NULL,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_user_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `user_role` (
`id` int(11) NOT NULL auto_increment ,
`user_id` varchar(32) DEFAULT NULL,
`role_id` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_ur_user_id` (`user_id`),
KEY `fk_ur_role_id` (`role_id`),
CONSTRAINT `fk_ur_role_id` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_ur_user_id` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `t_user` (`id`, `username`, `password`, `name`) values('1','super','$2a$10$TJ4TmCdK.X4wv/tCqHW14.w70U3CC33CeVncD3SLmyMXMknstqKRe','超级管理员');
insert into `t_user` (`id`, `username`, `password`, `name`) values('2','admin','$2a$10$TJ4TmCdK.X4wv/tCqHW14.w70U3CC33CeVncD3SLmyMXMknstqKRe','系统管理员');
insert into `t_user` (`id`, `username`, `password`, `name`) values('3','itcast','$2a$10$8qmaHgUFUAmPR5pOuWhYWOr291WJYjHelUlYn07k5ELF8ZCrW0Cui','test02');
insert into `t_user` (`id`, `username`, `password`, `name`) values('4','stu1','$2a$10$pLtt2KDAFpwTWLjNsmTEi.oU1yOZyIn9XkziK/y/spH5rftCpUMZa','学生1');
insert into `t_user` (`id`, `username`, `password`, `name`) values('5','stu2','$2a$10$nxPKkYSez7uz2YQYUnwhR.z57km3yqKn3Hr/p1FR6ZKgc18u.Tvqm','学生2');
insert into `t_user` (`id`, `username`, `password`, `name`) values('6','t1','$2a$10$TJ4TmCdK.X4wv/tCqHW14.w70U3CC33CeVncD3SLmyMXMknstqKRe','老师1');
INSERT INTO `t_role` (`id`, `role_name`, `role_code`, `description`) VALUES('5','学生','student','学生');
INSERT INTO `t_role` (`id`, `role_name`, `role_code`, `description`) VALUES('7','老师','teacher','老师');
INSERT INTO `t_role` (`id`, `role_name`, `role_code`, `description`) VALUES('8','教学管理员','teachmanager','教学管理员');
INSERT INTO `t_role` (`id`, `role_name`, `role_code`, `description`) VALUES('9','管理员','admin','管理员');
INSERT INTO `t_role` (`id`, `role_name`, `role_code`, `description`) VALUES('10','超级管理员','super','超级管理员');
INSERT INTO user_role(id,user_id,role_id) VALUES(NULL, '1', '5'),(NULL, '1', '7'),(NULL, '2', '8'),(NULL, '3', '9'),(NULL, '4', '8'),(NULL, '5', '10') ;
1.3.2 explain the id
id field is a serial number select query is a set of numbers representing the order of execution or operation of the select clause of a query table. id case, there are three:
1) id represents the same sequence table is loaded from top to bottom.
explain select * from t_role r, t_user u, user_role ur where r.id = ur.role_id and u.id = ur.user_id ;
Results:
first load table → r → loading table ur u loading table (id loading the same from top to bottom)
2) different id id value, the higher the priority, the first to be executed.
EXPLAIN SELECT * FROM t_role WHERE id = (SELECT role_id FROM user_role WHERE user_id = (SELECT id FROM t_user WHERE username = 'stu1'));
Results:
. 3) have the same ID, but also different, exist. the same can be considered as a group id, down from the order of execution; in all groups, the larger the value of id, higher priority, the first run.
EXPLAIN SELECT * FROM t_role r , (SELECT * FROM user_role ur WHERE ur.`user_id` = '2') a WHERE r.id = a.role_id ;
1.3.3 explain 之 select_type
SELECT indicates the type of common values, as follows:
select_type | meaning |
---|---|
SIMPLE | Simple select query, the query does not contain subqueries or UNION |
PRIMARY | If the query contains any complex sub-queries, the outermost query mark for identification |
SUBQUERY | It contains a subquery in the SELECT list or WHERE |
DERIVED | Included in the FROM list subquery is marked DERIVED (derivative) MYSQL Based recursively executing the sub-queries, the results in a temporary table |
UNION | If after the second SELECT UNION appear, they are marked UNION; UNION if included in the FROM clause of a subquery, SELECT will be marked as the outer layer: DERIVED |
UNION RESULT | Get the results from the table SELECT UNION |
- Containing a statement subquery
result:EXPLAIN SELECT * FROM t_role r ,(SELECT * FROM user_role ur WHERE ur.`user_id` = '2') a WHERE r.id = a.role_id ; EXPLAIN SELECT * FROM t_role r ,(SELECT * FROM user_role ur WHERE ur.`user_id` = '2') a WHERE r.id = a.role_id ;
1.3.4 explain 之 table
Display data on which this line is a table
3.3.5 explain 之 type
type shows the type of access, it is a more important indicator, possible values:
type | meaning |
---|---|
NULL | MySQL does not access any tables, indexes, direct return results |
system | Table only one row (equal to the system tables), which is a special case of type const, generally does not appear |
const | Represented by the index once found, const for comparing the primary key or unique index. Because only one row of data matching, so fast. As will be placed where the primary key list, MySQL the query can be converted to a steady. const compared to a constant value to all parts of the "primary key" or "unique" index |
eq_ref | Similarly ref, the only difference is that the use of the index, primary key associated with the use of query, the query associated with a record of only one. Common in the primary key or unique index scan |
ref | Non-unique index scan returns all rows matching a single value. Accessing an index that is essentially, all return all rows (s) match a separate value |
range | Retrieve only rows which would return to using an index to select the rows. After emergence between where, <,>, in other operations. |
index | ALL is the difference between index and index type is just traversing the index tree, usually faster than ALL, ALL is through the data file. |
all | We will traverse the whole table to find matching rows |
The result value from best to worst is this:
NULL > system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
system > const > eq_ref > ref > range > index > ALL
In general, we need to ensure that at least the range query level best to achieve ref.