PL/SQL 性能分页游标(带过滤和固定结果大小)
PL/SQL performance paging cursor (with filtering and fixed result size)
我有一个 pl/sql 游标,它从定义的 rowid(由参数给定)开始,用于分页查询。
游标检索的行按特殊规则过滤 - 因此结果行不会立即返回,而是收集在 table 类型变量中。
在一个循环中,我从游标中获取更多数据,直到将 100 个“行”放入 table 类型变量。此结果从函数发回。
一切正常,但初始 sql 查询(打开游标)需要很长时间。
如果我限制 sql 语句中的行(在“WHERE rownum <= (100 + p_startfrom)”中注释),查询会快得多。但是我不知道我要通过循环和过滤来获取多少数据。
有没有办法通过不添加固定的“rownum <= where 子句来使函数更快?
function get_metadata(p_toquery in number, p_startfrom in number) return t_Table_metadata
is
v_result_tab t_Table_metadata;
v_return_tab t_Table_metadata := t_Table_metadata();
c_meta SYS_REFCURSOR;
v_size_per_fetch integer := 100;
begin
open c_meta for
'SELECT t_type_metadata(....)
FROM (
SELECT t.*, rownum r
FROM (
select ...
from ...
where attr1 = '|| p_toquery||'
order by create_date desc
) t
-- with this where-Clause much faster!! WHERE rownum <= (100 + p_startfrom)
) f
WHERE r >= '|| p_startfrom;
loop
fetch c_meta bulk collect into v_result_tab limit v_size_per_fetch;
for i in 1..v_result_tab.count loop
v_check_row_result := check_row(....);
if (v_check_row_result = 1 and v_return_tab.count < 100) then
v_return_tab.extend;
v_return_tab(v_return_tab.count) := v_result_tab(i);
end if;
end loop;
exit when v_result_tab.count = 0 or v_return_tab.count >= 100;
end loop;
close c_meta;
return v_return_tab;
end;
使用提示 FIRST_ROWS
要求 Oracle 将查询快速优化为 return 少量行。您仍然需要猜测 PL/SQL 循环所需的行数,但粗略猜测,如 1000,可能就足够了。
SELECT /*+ first_rows(1000) */ t_type_metadata(....)
正如其他人评论的那样,如果您可以将所有条件放入单个 SQL 语句中,那将是理想的。使用单个 SQL 语句,添加分页可以像这样简单:select ... offset 100 rows fetch next 100 rows only;
我有一个 pl/sql 游标,它从定义的 rowid(由参数给定)开始,用于分页查询。
游标检索的行按特殊规则过滤 - 因此结果行不会立即返回,而是收集在 table 类型变量中。
在一个循环中,我从游标中获取更多数据,直到将 100 个“行”放入 table 类型变量。此结果从函数发回。
一切正常,但初始 sql 查询(打开游标)需要很长时间。 如果我限制 sql 语句中的行(在“WHERE rownum <= (100 + p_startfrom)”中注释),查询会快得多。但是我不知道我要通过循环和过滤来获取多少数据。
有没有办法通过不添加固定的“rownum <= where 子句来使函数更快?
function get_metadata(p_toquery in number, p_startfrom in number) return t_Table_metadata
is
v_result_tab t_Table_metadata;
v_return_tab t_Table_metadata := t_Table_metadata();
c_meta SYS_REFCURSOR;
v_size_per_fetch integer := 100;
begin
open c_meta for
'SELECT t_type_metadata(....)
FROM (
SELECT t.*, rownum r
FROM (
select ...
from ...
where attr1 = '|| p_toquery||'
order by create_date desc
) t
-- with this where-Clause much faster!! WHERE rownum <= (100 + p_startfrom)
) f
WHERE r >= '|| p_startfrom;
loop
fetch c_meta bulk collect into v_result_tab limit v_size_per_fetch;
for i in 1..v_result_tab.count loop
v_check_row_result := check_row(....);
if (v_check_row_result = 1 and v_return_tab.count < 100) then
v_return_tab.extend;
v_return_tab(v_return_tab.count) := v_result_tab(i);
end if;
end loop;
exit when v_result_tab.count = 0 or v_return_tab.count >= 100;
end loop;
close c_meta;
return v_return_tab;
end;
使用提示 FIRST_ROWS
要求 Oracle 将查询快速优化为 return 少量行。您仍然需要猜测 PL/SQL 循环所需的行数,但粗略猜测,如 1000,可能就足够了。
SELECT /*+ first_rows(1000) */ t_type_metadata(....)
正如其他人评论的那样,如果您可以将所有条件放入单个 SQL 语句中,那将是理想的。使用单个 SQL 语句,添加分页可以像这样简单:select ... offset 100 rows fetch next 100 rows only;