在什么条件下ROWNUM = 1显着提高了"存在"syle查询中的性能

dar*_*jnz 5 sql oracle optimization plsql

我阅读了这个问题中的一些讨论,并且自己想到,在我的PL/SQL代码中,我在不使用ROWNUM = 1优化的地方都有"存在"样式查询.

我的问题是:

  1. ROWNUM = 1的引入是否会显着提高性能?
  2. 如果是这样,在什么条件下性能会得到特别改善(例如,大量连接,对未编制索引的列的约束,大型表,大型结果集)

我正在尝试确定是否值得重写所有现有查询以添加ROWNUM = 1优化.

我正在考虑的查询是可能有多个连接并且可能查询大表的查询.它们具有以下一般形式:

SELECT 1
INTO ln_count
FROM table_1, table_2...., table_n
WHERE <various joins and conditions>;

IF ln_count > 0 THEN
  <do stuff>
END IF;
Run Code Online (Sandbox Code Playgroud)

我正在考虑将它们改为:

SELECT 1
INTO ln_count
FROM table_1, table_2...., table_n
WHERE <various joins and conditions>
AND ROWNUM = 1;

IF <local variable> > 0 THEN
  <do stuff>
END IF;
Run Code Online (Sandbox Code Playgroud)

Mic*_*vda 7

它通过简单的单索引查找(例如表连接)无法解决查询,确实显着提高了性能(平均百分之几十).但是它有可能隐藏数据/应用程序错误.

让我们有一张桌子:

create table t (id number(10,0), padding varchar2(1000));  
Run Code Online (Sandbox Code Playgroud)

- 故意不要使用PK使示例尽可能简单.填充用于模拟每条记录中的实际数据负载

有很多记录:

insert into t (id, padding)
select rownum, rpad(' ', 1000) from dual connect by level < 10000
Run Code Online (Sandbox Code Playgroud)

现在,如果你问一些类似的话

select 1 into ll_exists
from t where id = 5;
Run Code Online (Sandbox Code Playgroud)

数据库必须遍历整个表,无论它是否找到第一个数据块中的唯一匹配记录(顺便说一下,我们无法知道,因为它可以通过多种不同的方式插入)或者最后一个.那是因为它不知道只有一个匹配的记录.另一方面,如果你使用...和rownum = 1,它会在找到记录后停止遍历数据,因为你告诉它没有(或不需要)另一个匹配的记录.

缺点是,如果数据包含多个可能的记录,则使用rownum约束可能会得到不确定的结果.如果查询是

select id into ll_id
from t where mod (id, 2) = 1
and rownum = 1;
Run Code Online (Sandbox Code Playgroud)

然后我可能会收到DB答案1以及3以及123 ...订单无法保证,这就是结果.(没有rownum子句我会得到一个TOO_MANY_ROWS异常.这取决于情况哪一个更糟)

如果你真的想要查询哪些测试存在,那么写它的方式.

begin

select 'It does' 
  into ls_exists
from dual where
exists (your_original_query_without_rownum);

do_something_when_it_does_exist
exception
  when no_data_found then
    do_something_when_it_doesn't_exist
end;
Run Code Online (Sandbox Code Playgroud)


akf*_*akf 5

优化的一个经验法则是不要这样做,除非你有一个需要修复的热点.但是,如果您对性能优势感到好奇,可能需要使用两者进行一些测试,以确定是否可以测量任何改进的性能.

维基百科援引 Donald Knuth的话说:

"我们应该忘记小的效率,比如大约97%的时间:过早的优化是所有邪恶的根源."