在更新查询中消除mysql文件排序

在更新查询中消除mysql文件排序,mysql,sql,query-optimization,filesort,Mysql,Sql,Query Optimization,Filesort,我有这样一个表,我用它在mysql中实现队列: 创建表“队列”( `id`int(10)无符号非空自动增量, `队列名称'varchar(255)不为空, `在更新当前时间戳时插入“时间戳非空默认当前时间戳”, `由'varchar(255)插入的_不为空, `已获取`时间戳为空默认为空, `由`varchar(255)默认值NULL获取, `延迟到`时间戳为空默认为空, `优先级'int(11)不为空默认值'0', `值`文本不为空, `状态'varchar(255)非空默认值'new', 主

我有这样一个表,我用它在mysql中实现队列:

创建表“队列”( `id`int(10)无符号非空自动增量, `队列名称'varchar(255)不为空, `在更新当前时间戳时插入“时间戳非空默认当前时间戳”, `由'varchar(255)插入的_不为空, `已获取`时间戳为空默认为空, `由`varchar(255)默认值NULL获取, `延迟到`时间戳为空默认为空, `优先级'int(11)不为空默认值'0', `值`文本不为空, `状态'varchar(255)非空默认值'new', 主键(`id`), 键`queue\u index`(`acquired`、`queue\u name`、`priority`、`id`) )ENGINE=InnoDB AUTO_INCREMENT=1默认字符集=utf8 我的问题是mysql在运行更新时使用filesort。执行非常慢(表中800k行的执行时间为5s)

描述更新队列集合acquired=“test”,其中acquired为NULL,队列_name=“q1”按优先级排序,id限制为1; +----+-------------+-------+-------+---------------+-------------+---------+-------------+--------+-----------------------------+ |id |选择|类型|类型|可能的|键|键|列|参考|行|额外| +----+-------------+-------+-------+---------------+-------------+---------+-------------+--------+-----------------------------+ |1 |简单|队列|范围|队列|索引|队列|索引| 772 |常数| 409367 |使用where;使用文件排序| +----+-------------+-------+-------+---------------+-------------+---------+-------------+--------+-----------------------------+ 奇怪的是,当我使用相同的WHERE条件和ORDER列运行SELECT查询时,没有使用filesort:

描述从获取为NULL的队列中选择id,并按优先级排序队列_name=“q1”,id限制为1; +----+-------------+-------+------+---------------+-------------+---------+-------------+--------+--------------------------+ |id |选择|类型|类型|可能的|键|键|列|参考|行|额外| +----+-------------+-------+------+---------------+-------------+---------+-------------+--------+--------------------------+ |1 |简单|队列|参考|队列|索引|队列|索引| 772 |常数| 409367 |使用where;使用索引| +----+-------------+-------+------+---------------+-------------+---------+-------------+--------+--------------------------+ (查询时间0秒)

有人知道如何避免在更新查询中使用filesort,或者如何提高其性能吗

问候,,
Matzz

在mysql论坛()上讨论后,我报告了错误(已验证)。 可以使用“选择更新”绕过此问题:

SET @update_id := -1;
SELECT (SELECT @update_id := id)
FROM queue
WHERE acquired IS NULL AND queue_name = "q1"
ORDER BY priority, id LIMIT 1;
FOR UPDATE;
UPDATE queue SET acquired = "test" WHERE id = @update_id;

可能是因为表中的主键。MySQL将在每次更新时检查密钥的不一致性。在MariaDB中,您可以禁用这些检查,这可能也适用于MySQL(请参阅) +----+-------------+-------+------+---------------+-------------+---------+-------------+--------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+-------------+---------+-------------+--------+--------------------------+ | 1 | SIMPLE | queue | ref | queue_index | queue_index | 772 | const,const | 409367 | Using where; Using index | +----+-------------+-------+------+---------------+-------------+---------+-------------+--------+--------------------------+
SET @update_id := -1;
SELECT (SELECT @update_id := id)
FROM queue
WHERE acquired IS NULL AND queue_name = "q1"
ORDER BY priority, id LIMIT 1;
FOR UPDATE;
UPDATE queue SET acquired = "test" WHERE id = @update_id;