在 MySQL 中优化 ORDER BY LIMIT 查询

Posted

技术标签:

【中文标题】在 MySQL 中优化 ORDER BY LIMIT 查询【英文标题】:Optimizing ORDER BY LIMIT queries in MySQL 【发布时间】:2011-03-05 11:57:00 【问题描述】:

在我的网络应用程序中,我制作了一个内部消息传递系统。我想在每个页面(用户查看消息的位置)上放置一个“上一个”和一个“下一个”链接。

为了获得下一个和上一个 id,我执行了两个查询:

对于上一个:

SELECT id FROM pages WHERE (id<$requestedPageId) ORDER BY id DESC LIMIT 1

对于下一个:

SELECT id FROM pages WHERE (id>$requestedPageId) ORDER BY id LIMIT 1

EXPLAIN 表示查询类型是“范围”,而 rows 列表示它将检查所有 id 小于或大于页面 id 的行(一个大数字)。 Extra 行显示“使用位置”。

似乎 mysql 忽略了我只想要一行。 MySQL 还不够聪明,无法优化这种查询,因此它会找到页面的行并前后搜索第一个匹配的行吗?

有没有更好的方法来获取下一页和上一页的 id?

补充说明:

这个问题似乎存在于每个 ORDER BY LIMIT 类型的查询中(例如:当我将一个长列表拆分为多个页面时。)。 Where 子句并非如此简单(我想让用户访问他有权访问的下一页/上一页。但不要加入。) WHERE 中出现的所有列都被索引(id 是主键) 变量受到保护以防注入。

编辑1:

所以我目前使用的查询:

SELECT id
FROM reports
WHERE (id<$requestedPageId) AND ((isPublic=1) OR (recipientId=$recipient))
ORDER BY id DESC
LIMIT 1

或者当我将其重新考虑为答案时:

SELECT MAX(id)
FROM reports
WHERE (id<$requestedPageId) AND ((isPublic=1) OR (recipientId=$recipient))

【问题讨论】:

【参考方案1】:

上一个

SELECT MAX(id) FROM pages WHERE id<$requestPageId

接下来

SELECT MIN(id) FROM pages WHERE id>$requestedPageId

【讨论】:

在这个简单的例子中优化了表。但是,只要我在 where 子句中添加了一个附加条件,它就会检查所有行。 (解释类型将是全部)。我将编辑我的原始帖子并输入我正在使用的查询。 您是否在 isPublic 和 recipientId 上设置了索引?【参考方案2】:

数据库按预期运行。由于小于号 (id

您无法将其设为“const”类型查询,但您可以使用索引、子查询和/或联合语句对其进行优化。

这里有一个查询来统治他们。我并不是说这是最好的解决方案,而只是解决问题的一种方法。首先,如果您创建两个索引,一个在 recipientId 上,另一个在 isPublic 上,这个查询会更好地工作。

SELECT
GREATEST(
  ( SELECT MAX( id ) FROM reports 
    WHERE id < $requestedPageId AND recipientId = $recipient ),
  ( SELECT MAX( id ) FROM reports 
    WHERE id < $requestedPageId AND isPublic = 1 )
) AS prev_id
LEAST(
  ( SELECT MIN( id ) FROM reports 
    WHERE id > $requestedPageId AND recipientId = $recipient ),
  ( SELECT MIN( id ) FROM reports 
    WHERE id > $requestedPageId AND isPublic = 1 )
) AS next_id

【讨论】:

以上是关于在 MySQL 中优化 ORDER BY LIMIT 查询的主要内容,如果未能解决你的问题,请参考以下文章

MySQL优化order by导致的 using filesort

MySQL 查询优化与 group by 和 order by rand

MySQL高级--- ORDER BY优化

MySQL优化:order by和limit

MySQL高级知识——ORDER BY优化

Mysql之order by|group by 排序优化