dar*_*jnz 5 sql oracle optimization plsql
我阅读了这个问题中的一些讨论,并且自己想到,在我的PL/SQL代码中,我在不使用ROWNUM = 1优化的地方都有"存在"样式查询.
我的问题是:
我正在尝试确定是否值得重写所有现有查询以添加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)
它通过简单的单索引查找(例如表连接)无法解决查询,确实显着提高了性能(平均百分之几十).但是它有可能隐藏数据/应用程序错误.
让我们有一张桌子:
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)