Oracle分页ROWNUM列> =值挑战

时间:2014-12-13 19:06:53

标签: oracle oracle11g pagination rownum

在oracle分页方面遇到一些麻烦。情况下:

表> 10亿行:

  • 测量(Id编号,分类VARCHAR,值NUMBER)

指数:

  • ON Measurement(Value)

我需要一个获取第一个匹配的查询以及按Value排序的以下2000个匹配项。我也想使用索引。

第一个想法:

SELECT * FROM Measurement WHERE Value >= 1234567890 
AND ROWNUM <= 2000 ORDER BY Value ASC

结果: 查询只返回它可以在表中找到的前2000个案例,从顶部开始,其中Value大于或等于1234567890,然后命令结果集升序。

第二个想法:

SELECT * FROM 
(SELECT * FROM Measurement WHERE Value >= 1234567890 ORDER BY Value ASC)
 WHERE ROWNUM <= 2000

结果: Oracle不理解ROWNUM应该限制内部查询的数量,因此oracle决定首先获取Value大于或等于1234567890的所有行,然后在返回前2000行之前对该巨型结果集进行排序。因为Oracle猜测表中的大多数数据都会被返回,所以它也会忽略对索引的任何使用。

这些方法都不可接受,因为第一种方法给出了错误的结果,第二种方法需要数小时。

Oracle中是否支持分页?

4 个答案:

答案 0 :(得分:0)

您可以使用以下

SELECT * FROM 
(SELECT Id, Classification, Value, ROWNUM Rank FROM Measurement WHERE Value >= 1234567890)
 WHERE Rank <= 2000
order by Rank

您无需在子查询中订购。根本没必要。 以上不是分页,而是我想的第一页。

答案 1 :(得分:0)

请尝试更多选项

SELECT  *
   FROM( SELECT /*+ FIRST_ROWS(2000) */   
          Id,
          Classification,
          Value,
          ROW_NUMBER() OVER (ORDER BY Value) AS rn
     FROM Measurement
     where Value > 1234567889 
       )
   WHERE rn <=2000;

Update1:​​ - 强制使用Value.Here IDX_ON_VALUE是衡量值中索引的名称

SELECT * FROM 
            (SELECT /*+ INDEX(a IDX_ON_VALUE) */* FROM Measurement
             a WHERE value >=1234567890 ) 
                ORDER BY a.Value ASC)
WHERE ROWNUM <= 2000

答案 2 :(得分:0)

不确定你是否为你的问题找到了解决方案,但是我要花两分钱:

第一个查询将无法满足您的要求,因为它将获取满足您查询的2000个随机记录,然后按顺序执行。

来到第二个查询:

Oracle将首先执行第二个查询,然后只移动到外部查询。因此,只有在执行内部查询后才会应用rownum过滤器。

你可以尝试以下方法,做INDEX FAST FULL SCAN,我已经在一张276万行的桌子上进行了测试,它的成本低于其他方法:

     SELECT * from Measurement
                where value in ( SELECT VALUE FROM 
                                  (SELECT Value FROM Measurement
                                    WHERE Value >= 1234567890 ORDER BY Value ASC)
                                    WHERE ROWNUM <= 2000)

希望它有助于

Vishad

答案 3 :(得分:0)

我想我喜欢潜在的解决方案。但是,这不是一个查询。

declare
cursor c is
SELECT * FROM Measurement WHERE Value >= 1234567890 ORDER BY Value ASC;
l_rec c%rowtype;
begin
    open c;
    for i in 1 .. 2000
    loop
        fetch c into l_rec;
        exit when c%notfound;
    end loop;
    close c;
end;
/