2015-05-26 136 views
2

我在其中一个存储过程中遇到了性能问题。 以下为伪代码:Oracle存储过程性能

PROCEDURE SP_GET_EMPLOYEEDETAILS(P_EMP_ID IN NUMBER, CUR_OUT OUT REF CURSOR) 
IS 
BEGIN 
    OPEN CUR_OUT FOR 
    SELECT EMP_NAME, EMAIL, DOB FROM T_EMPLOYEES WHERE EMP_ID=P_EMP_ID; 
END; 

上述的存储过程需要约20秒至返回的结果与设定假设P_EMP_ID = 100

然而,如果我硬编码雇员ID为100在存储过程中,存储过程在40毫秒内返回结果集。

因此,当该值是硬编码而不是读取参数值时,相同的存储过程对同一参数值的行为不同。

表T_EMPLOYEES有大约100万条记录,并且在EMP_ID列上有一个索引。

希望对此有任何帮助,以了解如何改进此存储过程的性能或者可能是此处存在的问题。

+1

我的第一个猜测是参数的类型(本例中为NUMBER)和数据库列的类型之间的错配,但由于您的代码只是伪代码,因此很难分辨这可能是案例... –

+0

我已验证该列的数据类型。这是NUMBER。 – Nick

回答

3

这可能是偏斜的数据分布和/或不完整的直方图和/或系统调整不佳的问题。

该查询的快速版本可能使用索引。缓慢的版本可能是在进行全表扫描。为了知道该怎么做,Oracle必须知道数据的基数(在你的情况下,将返回多少结果)。如果它认为会返回很多结果,它会直接进行并进行全表扫描,因为它不值得使用索引的开销。如果它认为会返回很少的结果,它将使用索引来避免扫描整个表格。

的问题是:

  1. 如果使用字面值,甲骨文确切地知道在哪里看直方图,看看有多少结果将被退回。如果使用绑定变量,则更为复杂。当然,在Oracle 10上它并没有很好地处理这个问题,只是猜测了基数。在Oracle 11上,我不确定它可以做什么,叫做“绑定变量窥视” - 请参阅SQL Plan Management

  2. 即使知道实际值,如果直方图不是最新的,它也会得到错误的值。

  3. 即使它能准确猜测返回多少结果,您仍然依赖于Oracle系统参数是否正确。

对于这最后一点...基本上,Oracle有一些参数,告诉它FTS如何快速认为是VS索引的查找速度有多快。如果这些不正确,即使速度较慢,也可能会执行FTS。请参阅Burleson

我的经验是,Oracle倾向于过早地执行FTS方式。理想情况下,随着结果集规模的扩大,从使用索引到使用FTS的过程中,应该会有一个平稳的过渡,但实际上这些系统似乎被设置为支持批量工作。

+0

非常感谢您的回复 – Nick

+0

没问题。我遇到过这个问题。如果您发现答案有用,请不要忘记进行投票。 – rghome