其中rownum = 1查询在Oracle中占用时间

我正在尝试执行类似的查询
select * from tableName where rownum=1
这个查询基本上是为了获取表的列名。表中有超过百万条记录。当我把上面的条件花了这么多时间来获取第一行时。是否有任何替代来获取第一行。     
已邀请:
试试这个:
select * from tableName where rownum<=1
有一些奇怪的ROWNUM错误,有时稍微改变查询会修复它。我以前见过这种情况,但我无法重现它。 以下是对类似问题的一些讨论:http://jonathanlewis.wordpress.com/2008/03/09/cursor_sharing/和http://forums.oracle.com/forums/thread.jspa?threadID=946740&tstart=1     
这个问题已经得到解答,我将仅提供一个解释,为什么有时滤波器ROWNUM = 1或ROWNUM <= 1可能导致响应时间长。 遇到ROWNUM过滤器(在单个表上)时,优化器将生成一个带有COUNT STOPKEY的FULL SCAN。这意味着Oracle将开始读取行,直到遇到前N行(此处N = 1)。完整扫描从第一个范围读取块到高水位线。 Oracle无法确定哪些块包含行而哪些块没有预先确定,因此将读取所有块,直到找到N行为止。如果第一个块为空,则可能导致许多读取。 考虑以下:
SQL> /* rows will take a lot of space because of the CHAR column */
SQL> create table example (id number, fill char(2000));

Table created

SQL> insert into example 
  2     select rownum, 'x' from all_objects where rownum <= 100000;

100000 rows inserted

SQL> commit;

Commit complete

SQL> delete from example where id <= 99000;

99000 rows deleted

SQL> set timing on
SQL> set autotrace traceonly
SQL> select * from example where rownum = 1;

Elapsed: 00:00:05.01

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=7 Card=1 Bytes=2015)    
   1    0   COUNT (STOPKEY)
   2    1     TABLE ACCESS (FULL) OF 'EXAMPLE' (TABLE) (Cost=7 Card=1588 [..])

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      33211  consistent gets
      25901  physical reads
          0  redo size
       2237  bytes sent via SQL*Net to client
        278  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
正如您所看到的,一致获取的数量非常高(对于单行)。在某些情况下可能会遇到这种情况,例如,您插入带有
/*+APPEND*/
提示的行(因此高于高水位线),并且您还会定期删除最旧的行,从而在段的开头处产生大量空白空间。     
当然,Oracle有元数据表可以用来获取列名,比如DB2中的
sysibm.syscolumns
表? 并且,在快速网络搜索之后,情况似乎如此:请参阅
ALL_TAB_COLUMNS
。 我会使用那些而不是去实际的表,像(未经测试):
SELECT   COLUMN_NAME
FROM     ALL_TAB_COLUMNS
WHERE    TABLE_NAME = "MYTABLE"
ORDER BY COLUMN_NAME;
如果您一心想找出查询速度慢的原因,那么您应该恢复标准方法:让您的DBMS为您解释查询的执行计划。对于Oracle,请参阅本文档的第9节。 在
Ask Tom - Oracle
上有一个对话似乎表明行号是在选择阶段之后创建的,这可能意味着查询无论如何都要检索所有行。
explain
可能有助于确定这一点。如果它包含
FULL
而不是
COUNT STOPKEY
,那么这可以解释性能。 除此之外,我对Oracle细节的了解也在减少,你将不得不进一步分析
explain
。     
您的查询正在执行全表扫描,然后返回第一行。 尝试
SELECT * FROM table WHERE primary_key = primary_key_value;
第一行,尤其是与ROWNUM相关的行,由Oracle任意决定。除非您提供ORDER BY子句,否则从查询到查询可能不一样。 因此,选择要过滤的主键值与获取单行的方法一样好。     
我认为你略微忽略了ROWNUM的概念 - 根据Oracle文档:“ROWNUM是一个伪列,它返回结果集中行的位置。在从数据库中选择记录并在执行ORDER之前评估ROWNUM BY条款。“ 所以它返回任何一行,它在结果集中考虑#1,在你的情况下将包含1M行。 您可能需要查看ROWID伪列:http://psoug.org/reference/pseudocols.html     
我最近遇到了你所描述的同样的问题:我想从非常大的表中选择一行作为快速,脏,简单的内省,而“rownum = 1”本身就表现得非常糟糕。以下是对我有用的补救措施。 选择某个索引的第一个项的max(),然后使用它选择“rownum = 1”的所有行的一小部分。假设我的表有一些关于数字“group-id”的索引,并比较一下:
 select * from my_table where rownum = 1;
 -- Elapsed: 00:00:23.69
有了这个:
 select * from my_table where rownum = 1
    and group_id = (select max(group_id) from my_table);
 -- Elapsed: 00:00:00.01
    

要回复问题请先登录注册