我有一个oracle sql查询,如下所示,
select *
from employees a, department b
where a.empoyee_id = 10
and a.dept_no = b.dept_no
and a.salary between 10000 and 20000
and a.start_date between date1 and date2
and a.end_date between date3 and date4
上面的查询工作正常,只需几秒钟即可获取结果。
但是如果把它转换成下面这样的存储过程,
Procedure GETDATA(
EMP_ID IN NUMBER,
MIN_SAl IN NUMBER,
MAX_SAL IN NUMBER,
MIN_START_DATE IN VARCHAR2,
MAX_START_DATE IN VARCHAR2,
MIN_END_DATE IN VARCHAR2,
MAX_END_DATE IN VARCHAR2,
RESULT OUT dataset
)
IS
BEGIN
open RESULT FOR
select * from employees a, department b
where EMPLOYEE_ID = EMP_ID AND a.dept_no = b.dept_no
and (MIN_SAl IS NULL OR MAX_SAL IS NULL) OR (a.salary between MIN_SAl and MAX_SAL)
and (MIN_START_DATE IS NULL OR MAX_START_DATE IS NULL) OR (a.start_date between MIN_START_DATE and MAX_START_DATE)
and (MIN_END_DATE IS NULL OR MAX_END_DATE IS NULL) OR (a.end_date between MIN_END_DATE and MAX_END_DATE);
END GETDATA;
exec getdata(10,null,null,null,null,null,null,:p)
上面的存储过程需要10秒以上,但是单独运行它的结果只需要几秒钟。我看到在where子句(salary,start\u date,end\u date)中为所有列添加了索引
我觉得约会标准要花更多的时间。我在谷歌上搜索并修改了起始日期和结束日期的数据类型,使之成为varchar的日期,但仍然没有成功。为什么它在存储过程中花费了更多的时间,但作为独立运行只需几秒钟?
2条答案
按热度按时间ruoxqz4g1#
使用CTA测试您的查询。你们会发现,完成这项工作几乎需要同样的时间。当您只选择表时,几乎所有的代码编辑器都会首先带来第一个可用的结果。
cs7cruho2#
我相信您的过程比sql查询运行得慢,因为您使用括号的顺序不对。在sql中,salary、start-and end \u date需要匹配,在过程salary中,start-or end \u date需要匹配。排得越多,时间就越多。
其次,语法
min_x IS NULL or max_x IS NULL or x BETWEEN min_x AND min_y
可能导致不同的执行计划。我用一个最小的例子来测试:查找存储过程的执行计划要复杂一些,您需要深入研究
V$SQLTEXT
找到你的sql_id
,输入DBMS_XPLAN
:sql和过程p1都有相同的执行计划
但是,过程p2有一个不同的计划,需要扫描6840个索引行而不是325个: