与带时间戳的订单相比,MySQL在“ ORDER BY ID DESC LIMIT 100”上的执行速度较慢

时间:2019-03-31 08:28:51

标签: mysql

让我们采取以下方案。

我们有

SELECT id 
  FROM table 
 WHERE name='name' 
 ORDER 
    BY id DESC 
 LIMIT 100

以及与LIMIT 5完全相同的查询。

LIMIT 100查询大约需要0.2s,而LIMIT 5查询大约需要0.008s。 (甚至更高的LIMIT的1000执行时间上升到2秒!)

现在我们使用时间戳代替id。

我们有

SELECT id 
  FROM table 
 WHERE name='name' 
 ORDER 
    BY timestamp DESC 
 LIMIT 100

,并再次使用LIMIT 5进行完全相同的查询。

LIMIT 100查询大约需要0.4s,而LIMIT 5查询也需要0.4s。 (将LIMIT设置为1000不会太大影响执行时间。

该表如下构建。 id是主键,并且auto_increment是活动的。该表有500.000行。有100个不变的名称。每隔10分钟,我们会将所有名称及其最近的更新(带有时间戳)插入到表中。这意味着我们的表如下所示:

+-----+-------+---------------------+--+--+
| id  | name  | timestamp           |  |  |
+-----+-------+---------------------+--+--+
| 1   | mark  | 2019-03-31 09:00:02 |  |  |
+-----+-------+---------------------+--+--+
| 2   | peter | 2019-03-31 09:00:02 |  |  |
+-----+-------+---------------------+--+--+
| 3   | john  | 2019-03-31 09:00:02 |  |  |
+-----+-------+---------------------+--+--+
| ... | ...   | ...                 |  |  |
+-----+-------+---------------------+--+--+
| 101 | mark  | 2019-03-31 09:10:02 |  |  |
+-----+-------+---------------------+--+--+
| 102 | peter | 2019-03-31 09:10:02 |  |  |
+-----+-------+---------------------+--+--+
| 103 | john  | 2019-03-31 09:10:02 |  |  |
+-----+-------+---------------------+--+--+

因此,在使用name ='mark'的查询之后,它应如下所示:

+-----+------+---------------------+--+--+
| id  | name | timestamp           |  |  |
+-----+------+---------------------+--+--+
| 501 | mark | 2019-03-31 09:50:02 |  |  |
+-----+------+---------------------+--+--+
| 401 | mark | 2019-03-31 09:40:02 |  |  |
+-----+------+---------------------+--+--+
| 301 | mark | 2019-03-31 09:30:02 |  |  |
+-----+------+---------------------+--+--+
| 201 | mark | 2019-03-31 09:20:02 |  |  |
+-----+------+---------------------+--+--+
| 101 | mark | 2019-03-31 09:10:02 |  |  |
+-----+------+---------------------+--+--+
| 1   | mark | 2019-03-31 09:00:02 |  |  |
+-----+------+---------------------+--+--+
| ... | ...  | ...                 |  |  |
+-----+------+---------------------+--+--+

我现在的问题是,与完全相同但由id DESC进行排序的查询相比,为什么LIMIT进行的排序在timestamp DESC较高的情况下执行这么慢(限制1000在2s以上) (极限1000约为0.4s)。

我试图更改表并将索引添加到id,但这并没有改变。 问题是否出在id之间的空隙上? (501,401,301 ...)。

经过三天的谷歌搜索和尝试不同的查询后,什么都没有改变,关于这个奇怪行为的我的问题尚未得到答案。

说明ID为ID的查询

+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| 1  | SIMPLE      | name  | index | NULL          | PRIMARY | 4       | NULL | 1000 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+

还有带时间戳的说明查询:

+----+-------------+-------+------+---------------+------+---------+------+--------+-----------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows   | Extra                       |
+----+-------------+-------+------+---------------+------+---------+------+--------+-----------------------------+
| 1  | SIMPLE      | name  | ALL  | NULL          | NULL | NULL    | NULL | 500000 | Using where; Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+--------+-----------------------------+

@ niklaz,id类型为int(10)

@scaisEdge

表架构:

+-----------+------------------+------+-----+---------+----------------+
| Field     | Type             | Null | Key | Default | Extra          |
+-----------+------------------+------+-----+---------+----------------+
| id        | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
+-----------+------------------+------+-----+---------+----------------+
| name      | varchar(10)      | NO   |     | NULL    |                |
+-----------+------------------+------+-----+---------+----------------+
| timestamp | timestamp        | NO   |     | NULL    |                |
+-----------+------------------+------+-----+---------+----------------+

1 个答案:

答案 0 :(得分:2)

间隙与列ID的内容无关。您应该尝试在表上添加复合冗余索引

 create index  idx1 on my_table(name, id) 

可能是与缓存值有关的差距..尝试在单独的会话中执行查询。