【问题标题】:How to select last N Rows without using an Index如何在不使用索引的情况下选择最后 N 行
【发布时间】:2011-12-29 04:10:39
【问题描述】:

我有一个包含多个条件的查询,用于从 500 万 行的表中提取数据。已经建立了一个复合索引来部分覆盖其中一些条件,以至于我无法用索引覆盖排序:

SELECT columns FROM Table WHERE conditions='conditions' ORDER BY id DESC LIMIT N;

id 本身就是一个auto-increment 列。由于使用了filesort,上述查询可能会非常慢(4-5s)。通过删除 ORDER BY 子句,我可以将查询速度提高 4 倍。然而,提取的数据将主要是旧数据。

由于可以对提取的数据进行后处理,因此我更感兴趣的是从结果集中大致最近的 N 行中提取数据。我的问题是,有没有办法做这样的事情:

SELECT columns FROM Table WHERE conditions='conditions' LIMIT -N;

因为我真的不需要排序,而且我知道底部 N 行包含更新数据的可能性很高。

【问题讨论】:

  • 您是否使用服务器端语言来构建查询?您可以运行一个只计算行数的查询,然后在限制范围内使用该数字。
  • @Brian Glaz:我正在使用 PHP。是的,我可以先数一数。但这不是花费时间的两倍吗?
  • 需要更多时间,是的。但是一个简单的SELECT COUNT(id) FROM table 通常运行得很快。
  • @Brian Glaz,它必须首先检查where 子句中的条件,这需要相当长的时间。

标签: mysql optimization


【解决方案1】:

给你。请记住,对任何索引列使用 ORDER BY 应该没有问题,包括 id

SET @seq:=0;
SELECT  `id` 
FROM (

SELECT @seq := @seq +1 AS  `seq` ,  `id` 
FROM  `Table` 
WHERE `condition` =  'whatever'
)t1
WHERE t1.seq
BETWEEN (
(

SELECT COUNT( * ) 
FROM  `Table` 
WHERE `condition` =  'whatever'
) -49
)
AND (

SELECT COUNT( * ) 
FROM  `Table` 
WHERE `condition` =  'whatever'
);

您可以将“-49”替换为如下表达式:-1 * ($quantity_desired -1);

还请查看此答案,因为它可能会对您有所帮助: https://stackoverflow.com/a/725439/631764

还有一个: https://stackoverflow.com/a/1441164/631764

【讨论】:

  • 我不明白你的回答。我的where 子句中有条件,但你没有。
  • 好的,检查一下。它应该可以工作,但我仍然不明白为什么你不能只使用 ORDER BY id DESC LIMIT 50
  • 谢谢,但它看起来很复杂......我需要的只是提取满足where 条件的最新 N 行。在这里,您正在检查条件三遍。它如何转化为更快的查询速度?
  • 我可以,但是由于filesort,速度很慢。如果没有order by,我可以更快地得到结果。
  • 查询已优化。我在一个有 400,000 行的表上测试了上述内容。它花了不到一秒钟的时间。问题是您的请求毫无意义。您要求我们提出替代方法来做一些非常简单的事情 SELECT ... ORDER BY ... DESC LIMIT x。
【解决方案2】:

使用 between 抓取最后“几”行:

SELECT columns 
FROM Table 
WHERE conditions = 'conditions'
AND id between (select max(id) from table) - 50 AND (select max(id) from table)
ORDER BY id
DESC LIMIT N;

此示例获取最后 50 行,但将有效地使用 id 索引。其他条件和排序将仅超过 50 行。应该是一种享受。

【讨论】:

  • 通过这样做,您实际上是从搜索分析中丢弃了 4,999,950 行数据。
  • 是的,这行不通,因为最后 50 行中可能有 0 个匹配行。他需要先执行匹配,然后取最后一行。请参阅我修改后的答案。
  • @ButtleButkus 但他说匹配的行基本上是最后几行:我更感兴趣的是从大约最新的 N 行中提取数据
  • 是的,我知道,但我认为他的意思是他想提取结果集的最后 N 行。 IE。他总是想要N行。您的查询可以返回 0 行,因为值的子集 BETWEEN (select max(id) from table) - 50 AND (select max(id) 可以与 WHERE 条件选择的子集有 0 重叠。
  • @Bohemian:很抱歉造成混乱。我想要的是结果集中的最后 N 行。我将对其进行编辑。
猜你喜欢
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
相关资源
最近更新 更多