Mysql uses USE INDEX() to optimize queries

grammar:

SELECT ... FROM TABLE [ {
    
    USE|IGNORE|FORCE} INDEX (key_list)] WHERE ...

USE INDEX

Used to provide a list of indexes that you want Mysql to refer to, so that Mysql will no longer consider using other available indexes

IGNORE

Tell Mysql to ignore one or more indexes

FORCE INDEX

Force Mysql to use a specific index


First look at the table structure of arena_match_index, everyone pay attention to the index structure of the table

CREATE TABLE `arena_match_index` (
  `tid` int(10) unsigned NOT NULL DEFAULT '0',
  `mid` int(10) unsigned NOT NULL DEFAULT '0',
  `group` int(10) unsigned NOT NULL DEFAULT '0',
  `round` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `day` date NOT NULL DEFAULT '0000-00-00',
  `begintime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  UNIQUE KEY `tm` (`tid`,`mid`),
  KEY `mid` (`mid`),
  KEY `begintime` (`begintime`),
  KEY `dg` (`day`,`group`),
  KEY `td` (`tid`,`day`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

Then look at the following sql:

SELECT round  FROM arena_match_index WHERE `day` = '2010-12-31' AND `group` = 18 AND `begintime` < '2010-12-31 12:14:28' order by begintime LIMIT 1;

The query condition of this sql shows that the index that may be used is begintimesum dg, but because the order by begintime sorting is used, mysql finally chooses to use begintimethe index, and the result of explain is:

mysql> explain SELECT round  FROM arena_match_index  WHERE `day` = '2010-12-31' AND `group` = 18 AND `begintime` < '2010-12-31 12:14:28' order by begintime LIMIT 1;
+----+-------------+-------------------+-------+---------------+-----------+---------+------+--------+-------------+
| id | select_type | table             | type  | possible_keys | key       | key_len | ref  | rows   | Extra       |
+----+-------------+-------------------+-------+---------------+-----------+---------+------+--------+-------------+
|  1 | SIMPLE      | arena_match_index | range | begintime,dg  | begintime | 8       | NULL | 226480 | Using where |
+----+-------------+-------------------+-------+---------------+-----------+---------+------+--------+-------------+

The result of explain shows that begintime220,000 records need to be scanned using the index. The performance of such a query is very bad. The actual execution also takes more than 30 seconds for the first execution (when there is no cached data).

In fact, the performance of this query using dgthe joint index is better, because there are only dozens of games in the same group on the same day, so the dgindex should be used first to locate the matching data set and then sort it, so how to tell mysql to use the specified index? Use the use index statement:

mysql> explain SELECT round  FROM arena_match_index use index (dg) WHERE `day` = '2010-12-31' AND `group` = 18 AND `begintime` < '2010-12-31 12:14:28' order by begintime LIMIT 1;
+----+-------------+-------------------+------+---------------+------+---------+-------------+------+-----------------------------+
| id | select_type | table             | type | possible_keys | key  | key_len | ref         | rows | Extra                       |
+----+-------------+-------------------+------+---------------+------+---------+-------------+------+-----------------------------+
|  1 | SIMPLE      | arena_match_index | ref  | dg            | dg   | 7       | const,const |  757 | Using where; Using filesort |
+----+-------------+-------------------+------+---------------+------+---------+-------------+------+-----------------------------+

The explain results show that dgonly 757 pieces of data need to be scanned using the joint index, and the performance has been directly improved by hundreds of times. The actual execution status also returns the query results almost immediately.

In the initial query statement, as long as the order by begintime is removed, mysql will use dgthe index, which once again confirms that the order by will affect the index selection strategy of mysql!

mysql> explain SELECT round  FROM arena_match_index  WHERE `day` = '2010-12-31' AND `group` = 18 AND `begintime` < '2010-12-31 12:14:28'  LIMIT 1;
+----+-------------+-------------------+------+---------------+------+---------+-------------+------+-------------+
| id | select_type | table             | type | possible_keys | key  | key_len | ref         | rows | Extra       |
+----+-------------+-------------------+------+---------------+------+---------+-------------+------+-------------+
|  1 | SIMPLE      | arena_match_index | ref  | begintime,dg  | dg   | 7       | const,const |  717 | Using where |
+----+-------------+-------------------+------+---------------+------+---------+-------------+------+-------------+

Through the above example, it can be said that mysql is not smart sometimes, and it cannot always make the best choice, and we developers still need to "tune" it!

From the article link, please click.

Guess you like

Origin blog.csdn.net/weixin_43743711/article/details/129188245