现有一个表(数据量不到3000):
CREATE TABLE `Test` (
`id` int(11) NOT NULL,
`city` varchar(50) NOT NULL,
`addr` varchar(50) NOT NULL,
KEY `city` (`city`,`addr`),
KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
看两种语句的执行计划是一样的:
mysql> explain select SQL_NO_CACHE id from Test where id in (1,2,5,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22);
+—-+————-+——-+——-+—————+——+———+——+——+————————–+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+——-+——-+—————+——+———+——+——+————————–+
| 1 | SIMPLE | Test | range | id | id | 4 | NULL | 18 | Using where; Using index |
+—-+————-+——-+——-+—————+——+———+——+——+————————–+
1 row in set (0.02 sec)
mysql> explain select SQL_NO_CACHE id from Test where id between 0 and 22;
+—-+————-+——-+——-+—————+——+———+——+——+————————–+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+—-+————-+——-+——-+—————+——+———+——+——+————————–+
| 1 | SIMPLE | Test | range | id | id | 4 | NULL | 18 | Using where; Using index |
+—-+————-+——-+——-+—————+——+———+——+——+————————–+
1 row in set (0.00 sec)
但是实际的profiles:
mysql> show profiles;
+———-+————+————————————————————————————————-+
| Query_ID | Duration | Query |
+———-+————+————————————————————————————————-+
| 1 | 0.01375400 | select SQL_NO_CACHE id from Test where id between 0 and 22 |
| 2 | 0.00043300 | select SQL_NO_CACHE id from Test where id in (1,2,5,7,9,10,11,12,13,14,15,16,17,18,19,20,21,22) |
+———-+————+————————————————————————————————-+
差距是后者时间只是前者的3.15%。同样是走索引的。
详细的:
mysql> show profile for query 1;
+——————————–+———-+
| Status | Duration |
+——————————–+———-+
| starting | 0.000047 |
| checking query cache for query | 0.000070 |
| Opening tables | 0.000013 |
| System lock | 0.000007 |
| Table lock | 0.000026 |
| init | 0.000020 |
| optimizing | 0.000011 |
| statistics | 0.013088 |
| preparing | 0.000337 |
| executing | 0.000007 |
| Sending data | 0.000090 |
| end | 0.000005 |
| end | 0.000003 |
| query end | 0.000005 |
| freeing items | 0.000014 |
| closing tables | 0.000005 |
| logging slow query | 0.000003 |
| cleaning up | 0.000003 |
+——————————–+———-+
18 rows in set (0.00 sec)
mysql> show profile for query 2;
+——————————–+———-+
| Status | Duration |
+——————————–+———-+
| starting | 0.000033 |
| checking query cache for query | 0.000093 |
| Opening tables | 0.000011 |
| System lock | 0.000005 |
| Table lock | 0.000008 |
| init | 0.000023 |
| optimizing | 0.000010 |
| statistics | 0.000132 |
| preparing | 0.000011 |
| executing | 0.000004 |
| Sending data | 0.000074 |
| end | 0.000003 |
| end | 0.000003 |
| query end | 0.000003 |
| freeing items | 0.000009 |
| closing tables | 0.000005 |
| logging slow query | 0.000002 |
| cleaning up | 0.000004 |
+——————————–+———-+
18 rows in set (0.00 sec)
差距主要在statistics这一步上,在同一索引上我猜测in()的这种显示的指定范围比between and效率高。
标签: between and, in(), MySQL, statistics
nice!
Thank you!@openregion