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 begintime
sum dg
, but because the order by begintime sorting is used, mysql finally chooses to use begintime
the 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 begintime
220,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 dg
the joint index is better, because there are only dozens of games in the same group on the same day, so the dg
index 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 dg
only 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 dg
the 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!