Sql 如何加快Oracle中的行数?

Sql 如何加快Oracle中的行数?,sql,oracle,oracle10g,row-number,Sql,Oracle,Oracle10g,Row Number,我有一个SQL查询,如下所示: SELECT * FROM( SELECT ..., row_number() OVER(ORDER BY ID) rn FROM ... ) WHERE rn between :start and :end 从本质上说,这是一部分一部分的顺序使事情变慢了。如果我去掉它,解释成本会下降1000倍。我试过这个: SELECT ... FROM ... WHERE rownum

我有一个SQL查询,如下所示:

SELECT * FROM(
    SELECT
        ...,
        row_number() OVER(ORDER BY ID) rn
    FROM
        ...
) WHERE rn between :start and :end
从本质上说,这是一部分一部分的顺序使事情变慢了。如果我去掉它,解释成本会下降1000倍。我试过这个:

SELECT 
    ...
FROM
    ...
WHERE
    rownum between :start and :end

但这并不能给出正确的结果。有什么简单的方法可以加快速度吗?或者我需要花更多的时间使用解释工具吗?

您的订单是按列索引的吗?如果不是,那是一个很好的开始。

花更多时间使用解释计划工具。如果看到表扫描,则需要更改查询


你的问题对我来说毫无意义。查询ROWID似乎是自找麻烦。该查询中没有关系信息。这是您遇到问题的真实查询还是您为说明问题而编写的示例?

在我看来,这就像是分页查询

从这篇ASKTOM文章中,大约90%的内容如下:


此外,您的查询也不尽相同,因此我不确定比较两者的成本有什么好处。

部分问题在于“开始”到“结束”的跨度有多大以及它们“存在”的位置。 假设表中有一百万行,需要567890到567900行,那么您将不得不接受这样一个事实,即需要遍历整个表,按id对几乎所有行进行排序,并计算出哪些行属于该范围

简而言之,这需要大量的工作,这就是为什么优化器会给它带来高成本的原因

这也不是一个索引可以帮助很多的东西。索引会给出顺序,但充其量,它会给你一个开始的地方,然后你继续阅读,直到你到达第567900个条目

如果您一次向最终用户显示10个项目,那么从数据库中抓取前100个项目,然后让应用程序将这100个项目分成10个块,这可能是值得的。

在Oracle中,行数效率很低

有关性能详细信息,请参阅我博客中的文章:

对于您的特定查询,我建议您将其替换为ROWNUM,并确保使用索引:

SELECT  *
FROM    (
        SELECT  /*+ INDEX_ASC(t index_on_column) NOPARALLEL_INDEX(t index_on_column) */
                t.*, ROWNUM AS rn
        FROM    table t
        ORDER BY
                column
        )
WHERE rn >= :start
      AND rownum <= :end - :start + 1
此查询将使用计数停止键

另外,请确保列不可为NULL,或者添加WHERE column not NULL条件

否则,索引不能用于检索所有值

请注意,在没有子查询的情况下,不能在:start和:end之间使用ROWNUM

ROWNUM总是最后指定,最后检查,这就是ROWNUM总是按顺序排列的方式,没有间隙

如果使用介于10和20之间的ROWNUM,满足所有其他条件的第一行将成为返回的候选行,临时指定为ROWNUM=1,并且无法通过介于10和20之间的ROWNUM测试

然后,下一行将是一个候选行,分配了ROWNUM=1和fail,等等,因此,最后,将不会返回任何行


这应该通过将ROWNUM放入子查询来解决。

实际上,它不是。但将其更改为索引行并没有帮助。不过,谢谢你提出了显而易见的建议-索引只有在访问路径可以使用该索引的情况下才有助于改善顺序,即您正在查找一系列ID。它是分页。这基本上就是查询至少对分页所做的。我刚刚删除了查询的其余部分,主要是因为它不重要。为了简洁起见,我删掉了所有的省略号。事实上,那篇文章帮助我编写了这个查询。我没有注意到关于按唯一ID排序的部分。还有一个我错过的查询优化器提示。明天我会在工作中尝试!;我觉得它看起来很熟悉。在分页查询中,第一行是一个令人惊奇的问题。这一点和Quassnoi的建议使我的查询几乎保持不变的时间!我希望我能选择两个答案:-这听起来很合适。我从200万张唱片中拿出了15000张。我们限制了一个查询所需的时间,同时拉入所有15k记录会导致超时。因此,我认为对结果进行分页可以防止出现这种情况。我想这只是意味着我将不得不经历一场要求更长超时的官僚主义噩梦。我希望你没有向用户发送15000行!工作起来很有魅力。然而,优化器的提示似乎并没有产生明显的影响。这意味着CBO足够聪明,能够获取索引。实际上,这里最重要的是ROWNUM,而不是ROW_NUMBER。但我仍然会留下提示或创建一个大纲,以防CBO改变主意:仅供参考,我还没有尝试使用这两种方法,但如果我尝试使用FIRST_行而不是INDEX_ASC和NOPARALLEL_INDEX进行查询,解释成本从25000到8,运行时间非常接近于固定时间,我可以像其中一条一样快速地提取所有记录,所以我甚至可能不需要再翻页了。我可能仍然会使用分页,以防记录计数突然出现峰值。+1但我遇到了一些困难 G我不得不使用最后一个例子,对上面提到的博客文章进行两个子查询