问题描述
我在使用 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
该表有 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 行 没有任何临时表或文件排序。然后外部部分将最多排序 20 行并提供“正确”的 10。
对于 OFFSET
,请参阅 http://mysql.rjweb.org/doc.php/index_cookbook_mysql#or