MYSQL tuning combat

A: basic data preparation

DROP TABLE IF EXISTS `tbl_user`;
CREATE TABLE `tbl_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `email` varchar(20) DEFAULT NULL,
  `age` tinyint(4) DEFAULT NULL,
  `type` int(11) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

INSERT INTO `tbl_user` VALUES 
('1', 'admin', '[email protected]', '18', '1', '2018-07-09 11:08:57'), 
( ' 2 ' , ' mengday ' , ' [email protected] ' , ' 31 is ' , ' 2 ' , ' 2018-07-09 11:09:00 ' ),
( ' 3 ' , ' mengdee ' , ' [email protected] ' , ' 20 ' , ' 2 ' , ' 2018-07-09 11:09:04 ' ),
('4', 'root', '[email protected]', '31', '1', '2018-07-09 14:36:19'), 
( ' . 5 ' , ' zhangsan ' , ' [email protected] ' , ' 20 is ' , ' . 1 ' , ' 2018-07-09 14:37:28 ' ),
( ' 6 ' , ' lysis ' , ' [email protected] ' , ' 20 ' , ' 1 ' , ' 07/09/2018 14:37:31 ' ),
( ' . 7 ' , ' wangwu ' , ' [email protected] ' , ' 18 is ' , ' . 1 ' , ' 2018-07-09 14:37:34 ' ),
( ' . 8 ' , ' zhaoliu ' , ' [email protected] ' , ' 22 is ' , ' . 1 ' , ' 2018-07-11 18:29:24 ' ),
( ' . 9 ' , ' Fengqi ' , ' [email protected] ' , ' . 19 ' , ' . 1 ' , ' 2018-07-11 18:29:32 ' );


DROP TABLE IF EXISTS `tbl_userinfo`;
CREATE TABLE `tbl_userinfo` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `address` varchar(255) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_userId` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

INSERT INTO `tbl_userinfo` VALUES 
( ' 1 ' , ' Shanghai ' , ' 1 ' ),
( ' 2 ' , ' Beijing ' , ' 2 ' ),
( ' 3 ' , ' Hangzhou ' , ' 3 ' ),
( ' 4 ' , ' Shenzhen ' , ' 4 ' ),
( ' 5 ' , ' Guangzhou ' , ' 5 ' ),
( ' 6 ' , ' Hainan ' , ' 6 ' );

II: five million data insertion

Inserting a few test data, using the index will also be required to insert additional data as the test data, the following data is inserted by storing pieces 500W procedure as the test data

- modify the mysql default end symbol, the default is the semicolon; but in the functions and stored procedures will be used to resolve a semicolon lead to incorrect
DELIMITER $$

- randomly generated string of a specified length
CREATE FUNCTION rand_string(n INT) RETURNS VARCHAR(255) 
BEGIN 
 # Define three variables
 DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
 DECLARE return_str VARCHAR(255) DEFAULT '';
 DECLARE i INT DEFAULT 0;

 WHILE i < n DO 
   SET return_str = CONCAT(return_str, SUBSTRING(chars_str, FLOOR(1+RAND()*52), 1));
   SET i = i + 1;
 END WHILE;
 RETURN return_str;
END $$

- Creating the insertion of a stored procedure
CREATE PROCEDURE insert_user(IN START INT(10), IN max_num INT(10))
BEGIN
    DECLARE i INT DEFAULT 0; 
    SET autocommit = 0;  
    REPEAT
        SET i = i + 1;
        INSERT INTO tbl_user VALUES ((START+i) ,rand_string(8), CONCAT(rand_string(6), '@random.com'), 1+FLOOR(RAND()*100), 3, NOW());
        UNTIL i = max_num
    END REPEAT;
   COMMIT;
END $$

- The command terminator modify back
DELIMITER ;

- call a stored procedure, insert five million data, we need time to wait for a while, waiting for the completion of execution
CALL insert_user(100001,5000000);
-- Query OK, 0 rows affected (7 min 49.89 sec) 

SELECT COUNT(*) FROM tbl_user;

3: Use index and less use of the index

Before using the index query

 

 

 

 

 Then create a username index query again (database card is dead, I do sqlyog)

With 40 seconds to create an index, true bit slow

 

 

 Then try the query, basically second checked, it is clear that efficiency gains

 

 

 Before that black window plus the index go up

 

Then remove an index, byusername

 

 

 

 

Four: explain command

 

 

explain arguments detailed

 

 

 

 

 

 

 

 

 View the index usage: show status like 'Handler_read%'

Handler_read_key: the higher the better
Handler_read_rnd_next: the lower the better

Query Optimizer:

  • Redefine the table associated with the order (optimizer to determine the order of the associated table based on statistics)
  • Converted to the outer connector connection (when connection is equal to the outer connector)
  • Use equivalent transformation rule (e.g., to remove 1 = 1)
  • Optimization count (), min (), max ()
  • Sub-query optimization
  • Early Termination inquiry
  • in optimal conditions

mysql sql statement can be viewed after the mysql optimizer and rewritten by EXPLAIN EXTENDED SHOW WARNINGS

The following figure we do not use * prompt queries should be written specifically for that column

 

 

Five: take the index case and without taking the index of

1. in walking Index

in operation can be avoided, avoid, if it can not avoid the need to carefully assess the number of elements in the set back control in the 1000's.

 

 

2. take the index range query

 

 但是条件必须是一个具体的值,如果条件为 now() 当前时间,则会导致全表扫描

 

 

3. 模糊查询只有左前缀使用索引

 

 

4. 反向条件不走索引 != 、 <> 、 NOT IN、IS NOT NULL

 

 一个优化的实例:

# 常见的对not in的优化,使用左连接加上is null的条件过滤
SELECT id, username, age FROM tbl_user WHERE id NOT IN (SELECT user_id FROM tbl_order);


SELECT u.id, u.username, u.age
FROM tbl_user u
LEFT JOIN tbl_order o ON u.id = o.user_id
WHERE o.user_id IS NULL;

5. 对条件计算(使用函数或者算数表达式)不走索引

使用函数计算不走索引,无论是对字段使用了函数还是值使用了函数都不走索引,解决办法通过应用程序计算好,将计算的结果传递给sql,而不是让数据库去计算

 

 

 

 

6. 查询时必须使用正确的数据类型

如果索引字段是字符串类型,那么查询条件的值必须使用引号,否则不走索引

7. or 使用索引和不使用索引的情况

or 只有两边都有索引才走索引,如果都没有或者只有一个是不走索引的

8. 用union少用or

尽量避免使用or,因为大部分or连接的两个条件同时都进行索引的情况几率比较小,应使用uninon代替,这样能走索引的走索引,不能走索引的就全表扫描。

 

9. 能用union all就不用union

union all 不去重复,union去重复,union使用了临时表,应尽量避免使用临时表

 

10. 复合索引

对于复合索引,如果单独使用右边的索引字段作为条件时不走索引的。即复合索引如果不满足最左原则leftmost不会走复合索引

暂未完成,更新还会继续

Guess you like

Origin www.cnblogs.com/super-hu/p/12128522.html