SQL 使用 ORDER BY 的简单查询变慢

SQL gets slow on a simple query with ORDER BY

我遇到了 MySQL ORDER BY 的问题,它减慢了查询速度,我真的不知道为什么,我的查询有点复杂,所以我将它简化为一个简单的查询,没有加入了,但它仍然工作得非常慢。

查询:

SELECT
    W.`oid`
FROM
    `z_web_dok` AS W
WHERE
    W.`sent_eRacun` = 1 AND W.`status` IN(8, 9) AND W.`Drzava` = 'BiH'
ORDER BY W.`oid` ASC 
LIMIT 0, 10

table 有 946,566 行,内存占用 500 MB,我选择的那些字段的索引如下:

oid - INT PRIMARY KEY AUTOINCREMENT
status - INT INDEXED
sent_eRacun - TINYINT INDEXED
Drzava - VARCHAR(3) INDEXED

我先贴出解释查询的截图:

接下来是对数据库执行的查询:

这是去掉ORDER BY后的速度。

我也尝试过使用 DATETIME 字段进行排序,该字段也已编入索引,但我得到的查询速度与使用主键排序的查询一样慢,这是从今天开始的,通常总是快速而轻便。 什么会导致这样的事情?

您在此处使用的查询类型需要复合 covering index。这个应该可以很好地处理您的查询。

CREATE INDEX someName ON z_web_dok (Drzava, sent_eRacun, status, oid);

为什么这行得通?您正在寻找前三列的相等匹配项,并在第四列进行排序。查询规划器将使用这个索引来满足整个查询。它可以随机访问索引以找到与您的查询匹配的第一行,然后扫描索引以获得它需要的行。

专业提示:单列索引通常对性能有害,除非它们恰好符合应用程序中特定查询的要求,或者用于主键或外键。您通常会选择索引来匹配最活跃或最慢的查询。 编辑 您询问为应用程序中的每个查询创建特定索引是否更好。答案是是的。

可能还有更快的方法。 (或者它可能不会更快。)

IN(8, 9) 妨碍了完全有效地轻松处理 WHERE..ORDER BY..LIMIT。可能的解决方案是将其视为 OR,然后转换为 UNION 并使用 LIMIT 做一些技巧,特别是如果您也可能使用 OFFSET.

( SELECT ... WHERE .. = 8 AND ... ORDER BY oid LIMIT 10 )
UNION ALL
( SELECT ... WHERE .. = 9 AND ... ORDER BY oid LIMIT 10 )
ORDER BY oid LIMIT 10

这将允许 OJones 描述的覆盖索引在每个子查询中得到充分使用。此外,每个将提供最多 10 行 没有 任何临时 table 或文件排序。然后外部将最多排序 20 行并提供 'correct' 10.

对于 OFFSET,参见 http://mysql.rjweb.org/doc.php/index_cookbook_mysql#or