使用RefCursor准备语句与存储过程

时间:2011-06-07 06:05:11

标签: c# .net performance oracle oracle11g

我一直在调用在我的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语句可以返回大量结果。可能有数千行。

1 个答案:

答案 0 :(得分:1)

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

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