between and 和 in()一个对比

现有一个表(数据量不到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效率高。

标签: , , ,

2 条评论 发表在“between and 和 in()一个对比”上

  1. openregion 说:

    nice!

留下回复