Prepared语句与带有RefCursor的存储过程

本文关键字:RefCursor 存储过程 语句 Prepared | 更新日期: 2023-09-27 17:58:44

我一直在调用在C#应用程序中返回RefCursors的Oracle存储过程。下面给出了一个示例存储过程。

CREATE OR REPLACE
PROCEDURE "DOSOMETHING"(
    P_RECORDS OUT SYS_REFCURSOR)
AS
BEGIN
    OPEN P_RECORDS FOR
    SELECT SOMETHING FROM SOMETABLE;
END;

当使用OracleDataReader为此读取结果时,每次调用过程时,数据库都会解析该过程。经过大量的搜索,我发现在使用RefCursor时,.NET不可能消除这种解析调用。

但是,如果我只是使用如下所示的准备好的语句来调用该过程,则可以避免这种解析调用。

public void DoSomething()
{
    var command = ServerDataConnection.CreateCommand();
    command.CommandType = CommandType.Text;
    command.CommandText = "SELECT SOMETHING FROM SOMETABLE";
    command.Prepare();
    using (var reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            DoSomethingToResult();
        }
    }
}

我的问题是,以下哪种方法对性能的影响最小?将过程更改为准备好的语句以避免解析调用会对应用程序性能产生更负面的影响吗?

请注意,这些select语句可以返回大量结果。可能有数千行。

Prepared语句与带有RefCursor的存储过程

在PL/SQL中使用ref游标将在每次打开游标时引发解析调用。每次调用command.Prepare()时都会发出相同的解析调用。现在,您的.NET代码将像解析PL/SQL代码一样解析查询。

如果需要发出完全相同的查询(只需更改参数),则可以重用命令对象,而无需额外的解析调用。然而,这些解析将是软解析,因此性能可能并不显著(大部分工作都是在硬解析中完成的,这是数据库第一次遇到查询)。由于查询返回了很多行,因此与实际获取这些行的工作量相比,软解析所涉及的工作量肯定可以忽略不计。