sql optimization of MySql with order by and limit

Keywords: SQL MySQL

sql optimization of MySql with order by and limit

(root@localhost:mysql.sock)[mm]explain select ID,ModeType,BusinessID,BusinessList,FlowStatus,CreateTime,Name,LastStepStatus  FROM Rec_FS  where FlowStatus <>2 and LastStepStatus = 1 ORDER BY CreateTime ASC LIMIT 0,100;
+----+-------------+-----------------+------+------------------------------------------+----------------+---------+-------+---------+-----------------------------+
| id | select_type | table           | type | possible_keys                            | key            | key_len | ref   | rows    | Extra                       |
+----+-------------+-----------------+------+------------------------------------------+----------------+---------+-------+---------+-----------------------------+
|  1 | SIMPLE      | Rec_FS | ref  | FlowStatus,LastStepStatus,Idx_CreateTime | LastStepStatus | 5       | const | 1183769 | Using where; Using filesort |
+----+-------------+-----------------+------+------------------------------------------+----------------+---------+-------+---------+-----------------------------+
1 row in set (0.00 sec)

Take the index LastStepStatus, consume 118,3769 rows, and do filesort sort, execution completed 8 seconds.

(root@localhost:mysql.sock)[mm]show create table Rec_FS \G ;
*************************** 1. row ***************************
       Table: Rec_FS
Create Table: CREATE TABLE `Rec_FS` (
....
  KEY `ModeType` (`ModeType`) USING BTREE,
  KEY `FlowStatus` (`FlowStatus`) USING BTREE,
  KEY `LastStepStatus` (`LastStepStatus`) USING BTREE,
  KEY `Idx_CreateTime` (`FlowStatus`,`LastStepStatus`,`CreateTime`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)

Look at the table structure, the index Idx_CreateTime does not meet the current optimal execution plan of SQL, unreasonable writing, the system chooses LastStepStatus index

According to ORDER BY CreateTime ASC LIMIT 0,100, this SQL only needs to grab the first 100 lines containing CreateTime ascending order, LastStepStatus classified as 1, FlowStatus <> 2.
There is no need to crawl through the index LastStepStatus to satisfy the condition, sort again, and take another 100 rows.

Rewrite the index Idx_CreateTime
create inex idx_LastStepStatus2 on Rec_FS(CreateTime,LastStepStatus,FlowStatus) ;

(root@localhost:mysql.sock)[mm]explain select ID,ModeType,BusinessID,BusinessList,FlowStatus,CreateTime,Name,LastStepStatus  FROM Rec_FS use index(idx_LastStepStatus2) where FlowStatus <>2 and LastStepStatus = 1 ORDER BY CreateTime ASC LIMIT 0,100;
+----+-------------+-----------------+-------+---------------+---------------------+---------+------+------+-------------+
| id | select_type | table           | type  | possible_keys | key                 | key_len | ref  | rows | Extra       |
+----+-------------+-----------------+-------+---------------+---------------------+---------+------+------+-------------+
|  1 | SIMPLE      | Rec_FS | index | NULL          | idx_LastStepStatus2 | 109     | NULL |  100 | Using where |
+----+-------------+-----------------+-------+---------------+---------------------+---------+------+------+-------------+
1 row in set (0.00 sec)

idx_LastStepStatus2 scans only 100 rows, eliminating the sort brought about by order by. The whole SQL runs in 0.00 seconds

Posted by jayshields on Thu, 07 Feb 2019 19:06:16 -0800