17

如果我将查询限制为 1 而不是 5,我注意到速度会急剧下降。

SELECT he. *
FROM homematic_events he
WHERE he.homematic_devices_id =30
ORDER BY id DESC
LIMIT 1 

代替

SELECT he. *
FROM homematic_events he
WHERE he.homematic_devices_id =30
ORDER BY id DESC
LIMIT 5

我的表包含大约 12,000,000 行,结构如下:

CREATE TABLE IF NOT EXISTS `homematic_events` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `homematic_devices_id` int(11) DEFAULT NULL,
  `address` char(16) COLLATE utf8_unicode_ci NOT NULL,
  `interface_id` char(16) COLLATE utf8_unicode_ci NOT NULL,
  `key` char(32) COLLATE utf8_unicode_ci NOT NULL,
  `value` float(12,2) NOT NULL,
  `timestamp` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `timestamp` (`timestamp`),
  KEY `address` (`address`),
  KEY `key` (`key`),
  KEY `homematic_devices_id` (`homematic_devices_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=12637557 ;

这些是对 LIMIT 5 的速度测量的解释:

  mysql> EXPLAIN SELECT he. * FROM homematic_events he WHERE he.homematic_devices_id =30 ORDER BY id DESC LIMIT 5;
  +----+-------------+-------+------+----------------------+----------------------+---------+-------+------+-----------------------------+
  | id | select_type | table | type | possible_keys        | key                  | key_len | ref   | rows | Extra                       |
  +----+-------------+-------+------+----------------------+----------------------+---------+-------+------+-----------------------------+
  |  1 | SIMPLE      | he    | ref  | homematic_devices_id | homematic_devices_id | 5       | const | 4171 | Using where; Using filesort |
  +----+-------------+-------+------+----------------------+----------------------+---------+-------+------+-----------------------------+


starting                          0.000010
checking query cache for query    0.000030
Opening tables                    0.000007
System lock                       0.000004
Table lock                        0.000015
init                              0.000019
optimizing                        0.000007
statistics                        0.000098
preparing                         0.000012
executing                         0.000002
Sorting result                    0.022965
Sending data                      0.000047
end                               0.000004
query end                         0.000002
freeing items                     0.000302
storing result in query cache     0.000009
logging slow query                0.000002
cleaning up                       0.000003

这些是对 LIMIT 1 的速度测量的解释:

mysql> EXPLAIN SELECT he. * FROM homematic_events he WHERE he.homematic_devices_id =30 ORDER BY id DESC LIMIT 1;
+----+-------------+-------+-------+----------------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys        | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+----------------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | he    | index | homematic_devices_id | PRIMARY | 4       | NULL | 3029 | Using where |
+----+-------------+-------+-------+----------------------+---------+---------+------+------+-------------+

starting                              0.000010
checking query cache for query        0.000034
Opening tables                        0.000009
System lock                           0.000004
Table lock                            0.000015
init                                  0.000020
optimizing                            0.000008
statistics                            0.000069
preparing                             0.000016
executing                             0.000002
Sorting result                        0.000005
Sending data                        502.290180
end                                   0.000010
query end                             0.000003
freeing items                         0.000293
logging slow query                    0.000004
logging slow query                    0.000002
cleaning up                           0.000003

谁能向我解释这种行为?我提到这是由于 udes 具有 LIMIT 1 的不同索引的结果。但是为什么 mysql 对不同的 LIMIT 值使用不同的键?

4

3 回答 3

8

使用 LIMIT 1,我猜查询分析器会压缩主键并找到最后一条记录homematic_devices_id =30- 大概是因为分析器知道“排序”操作会更昂贵。

When you LIMIT 5, I'm guessing the query analyzer decides to find the records first, and then sort them. If you want to speed that operation up, you can create an index on both homematic_devices_id and ID like so: ALTER TABLE homematic_events_test ADD INDEX ( homematic_devices_id, id ) - by putting the device ID first, you accomodate the "Where" clause, and the ID column helps the SORT

于 2013-03-17T11:37:01.297 回答
3

出于某种原因,MySQL 使用主键 ,ID来访问这些行而不是索引会更快。即使您的查询专门使用了为其homematic_devices_id构建索引的字段。我也觉得奇怪的是,第二种情况下的 MySQL 只有homematic_devices_idunder possible_keys,然后选择PRIMARY了。通常,MySQL 会PRIMARY在该列中同时显示索引和其他可能的索引。

这可能是一个数据相关的问题吗?您是否尝试过使用其他 device_ids 进行查询?

尝试FORCE INDEX在这两种情况下使用,看看是否可以解决问题。

于 2013-03-17T11:22:45.933 回答
1

我的假设是,当您拥有并order by与 a 结合时limit 1,请求在内部被视为 a max()(或 min),可以通过索引立即到达,而当您请求 a 时limit 5,必须首先完成排序。

于 2013-03-17T11:25:36.520 回答