Mysql 为什么我的BIGINT(20)订单要花这么长时间?

Mysql 为什么我的BIGINT(20)订单要花这么长时间?,mysql,sql,optimization,indexing,query-optimization,Mysql,Sql,Optimization,Indexing,Query Optimization,我正在努力改进我的查询,这样就不会花那么长时间。有什么我可以试试的吗 我正在使用InnoDB 我的桌子: mysql> describe hunted_place_review_external_urls; +--------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra |

我正在努力改进我的查询,这样就不会花那么长时间。有什么我可以试试的吗

我正在使用InnoDB

我的桌子:

mysql> describe hunted_place_review_external_urls;
+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| id           | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| worker_id    | varchar(255) | YES  | MUL | NULL    |                |
| queued_at    | bigint(20)   | YES  | MUL | NULL    |                |
| external_url | varchar(255) | NO   |     | NULL    |                |
| place_id     | varchar(63)  | NO   | MUL | NULL    |                |
| source_id    | varchar(63)  | NO   |     | NULL    |                |
| successful   | tinyint(1)   | NO   |     | 0       |                |
+--------------+--------------+------+-----+---------+----------------+
我的问题是:

mysql> select * from hunted_place_review_external_urls where worker_id is null order by queued_at asc limit 1;

1 row in set (4.00 sec)

mysql> select count(*) from hunted_place_review_external_urls where worker_id is null;
+----------+
| count(*) |
+----------+
|    19121 |
+----------+
1 row in set (0.00 sec)
为什么即使我在
上有一个在
工人id上排队的索引,也要花4s

下面是此查询的
解释:

mysql> explain select * from hunted_place_review_external_urls where worker_id is null order by queued_at asc limit 1;
+----+-------------+-----------------------------------+-------+---------------+-----------+---------+------+------+-------------+
| id | select_type | table                             | type  | possible_keys | key       | key_len | ref  | rows | Extra       |
+----+-------------+-----------------------------------+-------+---------------+-----------+---------+------+------+-------------+
|  1 | SIMPLE      | hunted_place_review_external_urls | index | worker_id     | queued_at | 9       | NULL |   67 | Using where |
+----+-------------+-----------------------------------+-------+---------------+-----------+---------+------+------+-------------+
1 row in set (0.00 sec)
当我通过在
部分排队来删除
订单时,速度会快得多:

mysql> select * from hunted_place_review_external_urls where worker_id is null limit 1;

1 row in set (0.00 sec)
计数(*)
较小时,它也会变得更快:

mysql> select count(*) from hunted_place_review_external_urls where worker_id is null;
+----------+
| count(*) |
+----------+
|    10    |
+----------+
1 row in set (0.00 sec)

mysql> select * from hunted_place_review_external_urls where worker_id is null order by queued_at asc limit 1;

1 row in set (0.00 sec)
My
queued \
值是以毫秒为单位表示的时间戳,例如
1398210069531

来自:

在某些情况下,MySQL无法使用索引来解析订单, 尽管它仍然使用索引查找与WHERE匹配的行 条款这些情况包括:

…剪断

用于获取行的键与中使用的键不同 订购人:

从t1中选择*,其中键2=按键1的恒定顺序

以及:

使用
解释选择。。。ORDER BY
,您可以检查MySQL是否可以使用 用于解析查询的索引。如果在中看到
正在使用文件排序
,则无法执行此操作
Extra

您的查询计划确认您的慢速查询正在使用
键处的
排队_。如果按删除
订单,则查询计划应改为使用
工人id
键。速度差异的一个可能原因是使用的钥匙不同

正如彼得·扎伊采夫在书中所说:

在不扫描和排序整个结果集的情况下执行ORDER BY with LIMIT是非常重要的,因此使用索引对其非常重要

例如,如果我不
SELECT*FROM sites ORDER BY date\u created DESC LIMIT 10我会在(创建日期)使用索引来快速获得结果集

现在,如果我有一些类似于
SELECT*的东西,它们来自于category\u id=5 ORDER BY date\u created DESC LIMIT 10

在这种情况下,按日期创建的索引也可以工作,但它可能不是最有效的–如果很少,则可以扫描表的大部分以找到10行。所以,索引(分类号,创建日期)将是更好的主意

根据此建议,您可以尝试创建一个复合索引
(worker\u id,queued\u at)
,用于此特定查询。如果由于某种原因无法添加其他索引,也可以尝试强制有序查询使用
worker\u id
索引,以便在排序之前缩小结果集

如果您可以重写此查询,这样就可以在不使用
的情况下找到所需的单行,因为MySQL将在应用
限制1
之前对结果进行排序。但我不知道你在这里的广泛目标,我不能说这是否可能。将任务拆分为以下两个查询如何

select MIN(queued_at) from hunted_place_review_external_urls where worker_id is null into @var;

select * from hunted_place_review_external_urls where worker_id is null and queued_at = @var;
或者作为子查询,如果您没有重复值的问题

select * from hunted_place_review_external_urls where queued_at in (select MIN(queued_at) from hunted_place_review_external_urls where worker_id is null);
发件人:

在某些情况下,MySQL无法使用索引来解析订单, 尽管它仍然使用索引查找与WHERE匹配的行 条款这些情况包括:

…剪断

用于获取行的键与中使用的键不同 订购人:

从t1中选择*,其中键2=按键1的恒定顺序

以及:

使用
解释选择。。。ORDER BY
,您可以检查MySQL是否可以使用 用于解析查询的索引。如果在中看到
正在使用文件排序
,则无法执行此操作
Extra

您的查询计划确认您的慢速查询正在使用键处的排队_。如果按删除
订单,则查询计划应改为使用
工人id
键。速度差异的一个可能原因是使用的钥匙不同

正如彼得·扎伊采夫在书中所说:

在不扫描和排序整个结果集的情况下执行ORDER BY with LIMIT是非常重要的,因此使用索引对其非常重要

例如,如果我不
SELECT*FROM sites ORDER BY date\u created DESC LIMIT 10我会在(创建日期)使用索引来快速获得结果集

现在,如果我有一些类似于
SELECT*的东西,它们来自于category\u id=5 ORDER BY date\u created DESC LIMIT 10

在这种情况下,按日期创建的索引也可以工作,但它可能不是最有效的–如果很少,则可以扫描表的大部分以找到10行。所以,索引(分类号,创建日期)将是更好的主意

根据此建议,您可以尝试创建一个复合索引
(worker\u id,queued\u at)
,用于此特定查询。如果由于某种原因无法添加其他索引,也可以尝试强制有序查询使用
worker\u id
索引,以便在排序之前缩小结果集

如果您可以重写此查询,这样就可以在不使用
的情况下找到所需的单行,因为MySQL将在应用
限制1
之前对结果进行排序。但我不知道你在这里的广泛目标,我不能说这是否可能。将任务拆分为以下两个查询如何

select MIN(queued_at) from hunted_place_review_external_urls where worker_id is null into @var;

select * from hunted_place_review_external_urls where worker_id is null and queued_at = @var;
或者作为子查询,如果您没有重复值的问题

select * from hunted_place_review_external_urls where queued_at in (select MIN(queued_at) from hunted_place_review_external_urls where worker_id is null);
发件人:

在某些情况下,MySQL无法使用索引来解析订单, 尽管它仍然使用索引查找与WHERE匹配的行 条款这些情况包括:

…剪断

用于获取行的键与中使用的键不同 订购人:

从t1中选择*,其中键2=按键1的恒定顺序

以及:

使用
解释选择。。。ORDER BY
,您可以检查MySQL是否可以使用 用于解析查询的索引。如果看到
正在使用文件,则无法执行此操作